当前位置: 首页 > news >正文

辽宁东方建设工程有限公司网站莱芜百度网站建设

辽宁东方建设工程有限公司网站,莱芜百度网站建设,陕西省住房建设厅官网,做网站的公司那家好。JPA中自定义的插入、更新、删除方法为什么要添加Modifying注解和Transactional注解#xff1f;   前几天#xff0c;有个同事在使用JPA的自定义SQL方法时#xff0c;程序一直报异常#xff0c;捣鼓了半天也没能解决#xff0c;咨询我的时候#xff0c;我看了一眼他的程…JPA中自定义的插入、更新、删除方法为什么要添加Modifying注解和Transactional注解   前几天有个同事在使用JPA的自定义SQL方法时程序一直报异常捣鼓了半天也没能解决咨询我的时候我看了一眼他的程序差不多是这个样子的 1 Repository 2 public interface UserRepository extends JpaRepositoryUser,Long { 3 4 Query(value delete from pro_user where id ?1,nativeQuery true) 5 void deleteUserById(Long id); 6 }我告诉他你的deleteUserById方法缺少了Modifying注解和Transactional注解他半信半疑地试了一下然后果然就解决了。其实如果他查一下官方资料或许很快也就能找到答案。基于这个背景本文详细讲解一下为何我们自定义的插入、更新、删除操作需要加Modifying注解和Transactional注解。 一、Modifying注解   在官方资料中给出了这样几句说明 复制代码 As the queries themselves are tied to the Java method that executes them, you can actually bind them directly by using the Spring Data JPA Query annotation rather than annotating them to the domain class. You can modify queries that only need parameter binding by annotating the query method with Modifying The Modifying annotation is only relevant in combination with the Query annotation. Derived query methods or custom methods do not require this Annotation. Doing so triggers the query annotated to the method as an updating query instead of a selecting one. 复制代码   如下 Modifying Query(“update User u set u.firstname ?1 where u.lastname ?2”) int setFixedFirstnameFor(String firstname, String lastname);   第一句话的意思是可以用Query注解来将自定义sql语句绑定到自定义方法上。 第二句话的意思时可以用Modifying注解来标注只需要绑定参数的自定义的更新类语句更新、插入、删除。 第三名话的意思是说Modifying只与Query联合使用派生类的查询方法和自定义的方法不需要此注解如 复制代码 1 Repository2 public interface UserRepository extends JpaRepositoryUser,Long {3 4 // 父类的保存方法5 Override6 User save(User entity); 7 8 // 按照JPA语法规则自定义的查询方法9 ListUser findFirst10ByLastname(String lastName, Pageable pageable); 10 }复制代码   第四句话的意思是当加上Modifying注解时JPA会以更新类语句来执行而不再是以查询语句执行。 也就是说当我们要通过自已写的更新、插入、删除SQL语句来实现更新、插入、删除操作时至少需要用两个步骤 Query来注入我们自定义的sql 使用Modifying来标注是一个更新类的自定义语句。 按照这个规则修改同事的那个方法 复制代码 1 Repository 2 public interface UserRepository extends JpaRepositoryUser,Long { 3 4 Modifying 5 Query(value delete from pro_user where id ?1,nativeQuery true) 6 void deleteUserById(Long id); 7 }复制代码   但是此时该方法还不完整执行时程序会报以下错误 复制代码 org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:402) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255) … at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:398) at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1585) … 复制代码 二、Transactional注解   官方的说明 By default, CRUD methods on repository instances are transactional. For read operations, the transaction configuration readOnly flag is set to true. All others are configured with a plain Transactional so that default transaction configuration applies. For details, see JavaDoc of SimpleJpaRepository. If you need to tweak transaction configuration for one of the methods declared in a repository, redeclare the method in your repository interface, as follows: Example. Custom transaction configuration for CRUD 复制代码 1 public interface UserRepository extends CrudRepositoryUser, Long { 2 3 Override 4 Transactional(timeout 10) 5 public ListUser findAll(); 6 7 // Further query method declarations 8 }复制代码   这句话的意思是默认情况下repository 接口中的CRUD方法都是被Transactional注解修饰了的对于读的操作方法Transactional注解的readOnly属性是被设置为true的即只读CRUD中的其他方法被Transactional修饰即非只读。如果你需要修改repository 接口中的某些方法的事务属性可以在该方法上重新加上Transactional注解并设置需要的属性。 我们先来看一下Transactional注解的源码 复制代码 1 Target({ElementType.METHOD, ElementType.TYPE})2 Retention(RetentionPolicy.RUNTIME)3 Inherited4 Documented5 public interface Transactional {6 7 Propagation propagation() default Propagation.REQUIRED;8 9 Isolation isolation() default Isolation.DEFAULT; 10 11 int timeout() default -1; 12 13 boolean readOnly() default false; 14 15 // 其他省略 16 }复制代码   由上可见Transactional注解的readOnly默认的属性的false即非只读当一个事务是非只读事务的时候我们可以进行任何操作。 再看一下repository 接口的实现类SimpleJpaRepository的源码(只摘了部分源码) 复制代码 1 Repository2 Transactional(3 readOnly true4 )5 public class SimpleJpaRepositoryT, ID implements JpaRepositoryImplementationT, ID {6 7 Transactional8 public void deleteById(ID id) {9 Assert.notNull(id, The given id must not be null!); 10 this.delete(this.findById(id).orElseThrow(() - { 11 return new EmptyResultDataAccessException(String.format(No %s entity with id %s exists!, this.entityInformation.getJavaType(), id), 1); 12 })); 13 } 14 15 Transactional 16 public void delete(T entity) { 17 Assert.notNull(entity, The entity must not be null!); 18 this.em.remove(this.em.contains(entity) ? entity : this.em.merge(entity)); 19 } 20 21 Transactional 22 public void deleteAll(Iterable? extends T entities) { 23 Assert.notNull(entities, The given Iterable of entities not be null!); 24 Iterator var2 entities.iterator(); 25 26 while(var2.hasNext()) { 27 T entity var2.next(); 28 this.delete(entity); 29 } 30 } 31 32 public T getOne(ID id) { 33 Assert.notNull(id, The given id must not be null!); 34 return this.em.getReference(this.getDomainClass(), id); 35 } 36 37 public ListT findAll() { 38 return this.getQuery((Specification)null, (Sort)Sort.unsorted()).getResultList(); 39 } 40 41 public ListT findAll(Nullable SpecificationT spec) { 42 return this.getQuery(spec, Sort.unsorted()).getResultList(); 43 } 44 45 public ListT findAll(Nullable SpecificationT spec, Sort sort) { 46 return this.getQuery(spec, sort).getResultList(); 47 } 48 49 public S extends T long count(ExampleS example) { 50 return executeCountQuery(this.getCountQuery(new SimpleJpaRepository.ExampleSpecification(example), example.getProbeType())); 51 } 52 53 public S extends T boolean exists(ExampleS example) { 54 return !this.getQuery(new SimpleJpaRepository.ExampleSpecification(example), example.getProbeType(), (Sort)Sort.unsorted()).getResultList().isEmpty(); 55 } 56 57 Transactional 58 public S extends T S save(S entity) { 59 if (this.entityInformation.isNew(entity)) { 60 this.em.persist(entity); 61 return entity; 62 } else { 63 return this.em.merge(entity); 64 } 65 } 66 67 Transactional 68 public S extends T S saveAndFlush(S entity) { 69 S result this.save(entity); 70 this.flush(); 71 return result; 72 } 73 74 Transactional 75 public void flush() { 76 this.em.flush(); 77 } 78 }复制代码   从SimpleJpaRepository源码中可以看出 1该类上注解了只读事务Transactional(readOnly true) 2该类的所有查询类操作方法都与类相同都拥有只读事务3该类的所有保存、更新、删除操作方法都用Transactional重新注解了默认readOnlyfalse。说明JPA为我们提供的所有方法包括JPA规则的自定义方法在其底层都为我们做好了事务处理而我们自定义的方法需要自己来标注事务的类型是只读还是非只读。根据这个原理再次修改开篇所列出的方法 复制代码 1 Repository 2 public interface UserRepository extends JpaRepositoryUser,Long { 3 4 Transactional 5 Modifying 6 Query(value delete from pro_user where id ?1,nativeQuery true) 7 void deleteUserById(Long id); 8 }复制代码   至此该方法按所期望的结果运行成功了。 三、Modifying注解补充说明 复制代码 1 Retention(RetentionPolicy.RUNTIME) 2 Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) 3 Documented 4 public interface Modifying { 5 6 boolean flushAutomatically() default false; 7 8 boolean clearAutomatically() default false; 9 }复制代码   该注解中有两个属性flushAutomatically、clearAutomatically从字面理解是自动刷新和自动清除。 自动刷新即执行完语句后立即将变化内容刷新到磁盘如果是insert语句操作则与JPA的 S saveAndFlush(S entity);方法效果相同 自动清除即执行完语句后自动清除掉已经过期的实体比如我们删除了一个实体但是在还没有执行flush操作时这个实体还存在于实体管理器EntityManager中但这个实体已经过期没有任何用处直到flush操作时才会被删除掉。如果希望在删除该实体时立即将该实体从实体管理器中删除则可以将该属性设置为true如 1 Modifying(clearAutomatically true) 2 Transactional 3 Query(value delete from pro_user where id ?1,nativeQuery true) 4 void deleteUserById(Long id);
http://www.hkea.cn/news/14334270/

相关文章:

  • 建设协会网站网页剪辑app
  • 外国做图网站北京全包圆装修公司好不好
  • 网站系统 外贸用php怎么做网站
  • go 做视频网站网络舆情处置的五个步骤
  • 网络上建个网站买东西多少钱服务器更改wordpress
  • 网站做seo必要的结构如何分析竞争对手的网站
  • 佛山网站建设是哪个好做一个公司网站需要多少钱
  • 常州网站建设咨询怎么用wordpress仿站
  • 北京制作网站报价外贸英语网站
  • 360网站收录提交入口大全手机模板网站模板下载网站有哪些内容
  • 辽宁工程建设信息网网站武都区建设局网站
  • 微信页面设计网站WordPress社交评论
  • 上海网站建设联怎么样建设网站赚钱
  • 网站建设seo 视频教程鲜花店网站建设的规模设想
  • 做美团网站需要多少钱网站建设300
  • 电子商务网站概念wordpress 好用主题
  • 府网站建设先进个人展示商品的网站怎么做
  • 网站建设与管理实践收获中企动力网站后台
  • vue做网站电子商务网站建设与管理总结
  • 多多返利网站建设宁波seo推荐
  • 北京工程质量建设协会网站做公众号需要做网站吗
  • 网站建设与制作教学计划干部重庆网络学院
  • 北控京奥建设有限公司网站好大夫在线个人网站王建设
  • 两个域名指向同一个网站品牌vi设计设计生成
  • asp企业网站模板下载网站开发入门培训机构
  • 网站做外部链接搜索引擎优化网站的网址
  • 买了域名怎么做自己的网站鹤山区网站建设
  • 荥阳网站建设定制网站建设案例课堂
  • 自己做网站赚佣金做网站需要哪些成本
  • wordpress 建站对比app 设计网站建设