Spring JPA 自定义删改
Spring JPA 更新创建
之前介绍的方法,基本都是只读方法,查询创建没有对数据库中存储的实体进行任何修改,但是对于更新和删除来说,如果继续保持只读属性,那么改删功能是难以完成的。通过使用@modify
注释查询方法,您可以修改只需要参数绑定的查询,如下面的示例所示:
例:修改查询实例
@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
这样做被注释的方法的查询将会作为更新查询而不是选择查询,由于EntityManager
在执行了修改的查询之后可能返回之前的查询结果,如果您希望EntityManager
被自动清除,您可以将@ modify
注释的clearautomatic
属性设置为true
。该注解中有两个属性:flushAutomatically
、clearAutomatically
,从字面理解是自动刷新和自动清除。
自动刷新,即执行完语句后立即将变化内容刷新到磁盘,如果是insert
语句操作,则与JPA的<S extends T> S saveAndFlush(S entity);
方法效果相同;
自动清除,即执行完语句后自动清除掉已经过期的实体,比如,我们删除了一个实体,但是在还没有执行flush
操作时,这个实体还存在于实体管理器EntityManager
中,但这个实体已经过期没有任何用处,直到flush操作时才会被删除掉。如果希望在删除该实体时立即将该实体从实体管理器中删除,则可以将该属性设置为true
,如:
@Modifying(clearAutomatically = true)
@Transactional
@Query(value = "delete from pro_user where id = ?1",nativeQuery = true)
void deleteUserById(Long id);
派生删除
Spring Data JPA还支持派生的delete查询,使您不必显式声明JPQL查询,如下面的示例所示:
例:使用派生删除查询
interface UserRepository extends Repository<User, Long> {
void deleteByRoleId(long roleId);
@Modifying
@Query("delete from User u where u.role.id = ?1")
void deleteInBulkByRoleId(long roleId);
}
尽管deleteByRoleId()
方法看起来基本上会产生与deleteInBulkByRoleId()
相同的结果,但就执行方式而言,这两个方法声明之间有一个重要的区别。顾名思义,后一种方法对数据库发出单个JPQL
查询(在注释中定义的查询)。这意味着即使当前加载的User
实例也没有看到该命周期回调被触发。
为了确保实际调用生命周期查询,deleteByRoleId()
的调用执行一个查询,然后逐个删除返回的实例,这样持久性提供者就可以对这些实体实际调用@PreRemove
回调。
实际上,派生的delete
查询是执行查询并在结果上调用CrudRepository.delete
(Iterable<User> users
)并保持行为与CrudRepository
中其他delete()
方法的实现同步的快捷方式。
事实上,如果直接运行以上自定义的的方法,可能会出现如下错误:
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)
.......
这是因为,默认情况下,repository
接口中的CRUD
方法都是被@Transactional
注解修饰了的,对于读的操作方法,@Transactional
注解的readOnly
属性是被设置为true
的,即只读;CRUD
中的其他方法被@Transactional
修饰,即非只读。如果你需要修改repository
接口中的某些方法的事务属性,可以在该方法上重新加上@Transactional
注解,并设置需要的属性。
例:修改后代码
@Modifying
@Transactional
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
参考文档
[1] https://www.cnblogs.com/wuhenzhidu/p/jpa.html [2] https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.modifying-queries
- [go语言]利用缓冲信道来实现网游帐号验证消息的分发和等待
- 转--Golang语言版 ssh口令破解工具
- cubieboard(树莓派)安装Ubuntu+Apache+PHP+Mysql
- Oracle 12c里的几点补充(一)(r11笔记第7天)
- Oracle备库的PDB无法连接的问题(r11笔记第6天)
- Golang语言社区--模板的使用
- Golang语言写Web 应用程序
- 强制wordpress后台HTTPS
- Golang语言 Cookie的使用
- Golang 语言调用动态库实现OpenGL及windows的API编程
- MySQL中的Online DDL(第一篇)(r11笔记第3天)
- 转--quick-cocos做客户端,golang做服务端,实现HTTP通信
- Nginx配置SSL证书
- Golang语言RPC Authorization进行简单ip安全验证的方法
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Linux 僵尸进程产生原因及解决方法
- Ubuntu17.04配置更换国内源的方法
- Centos7硬盘挂载方法
- linux sort多字段排序实例解析
- Linux中Centos7搭建Hadoop服务步骤
- Centos7实现磁盘限额设置方法
- 在CentOS中部署多节点Citus集群的详细步骤
- 建立自己的npm镜像服务器
- Hugo搭建博客(一)— 基本设置
- Canvas系列(1):直线图形
- 《进化:从孤胆极客到高效团队》读书笔记
- CentOS设置精准时间的方法
- Linux下sersync数据实时同步
- 浅析Centos7搭建samba服务器方法
- IOC XMLBeanDefinitionReader