使用SpringDataJPA更新实体
SpringDataJPA内置了一个save方法用于保存、更新实体内容,如果存在主键值则更新对应主键的row信息,反则是添加一条新信息,这一点跟Hibernate的saveOrUpdate方法比较相似。我们先来创建一个UserController控制器,代码如下所示:
package com.yuqiyu.querydsl.sample.chapter3.controller;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.yuqiyu.querydsl.sample.chapter3.bean.QUserBean;
import com.yuqiyu.querydsl.sample.chapter3.bean.UserBean;
import com.yuqiyu.querydsl.sample.chapter3.jpa.UserJPA;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
@RestController
public class UserController
{
@Autowired
private UserJPA userJPA;
//实体管理者
@Autowired
private EntityManager entityManager;
//JPA查询工厂
private JPAQueryFactory queryFactory;
@PostConstruct
public void initFactory()
{
queryFactory = new JPAQueryFactory(entityManager);
System.out.println("init JPAQueryFactory successfully");
}
}
上面这个控制器与第二章内的控制器基本内容没有什么差别,在bean构造函数初始化时通过EntityManager对象实例化JPAQueryFactory查询工厂实体,方便我们接下来的查询操作,QueryDsl形式是需要建立在JPAQueryFactory对象基础上构建的。SpringDataJPA方式更新实体代码如下:
/**
* 使用Jpa更新会员信息
* @param userBean
*/
@RequestMapping(value = "/updateWithJpa")
public String updateWithJpa(UserBean userBean)
{
//保存会员信息相当于Hibernate内的SaveOrUpdate
userJPA.save(userBean);
return "SUCCESS";
}
我们来看下控制台输出的日志内容,如下代码所示:
Hibernate:
select
userbean0_.t_id as t_id1_0_0_,
userbean0_.t_address as t_addres2_0_0_,
userbean0_.t_age as t_age3_0_0_,
userbean0_.t_name as t_name4_0_0_,
userbean0_.t_pwd as t_pwd5_0_0_
from
t_user userbean0_
where
userbean0_.t_id=?
Hibernate:
update
t_user
set
t_address=?,
t_age=?,
t_name=?,
t_pwd=?
where
t_id=?
可以看到SpringDataJPA先去数据库查询了一边当前对象,比对发现与数据库内不一致并且存在主键值则执行了下面的Update语句,这里如果查询到的字段对应更新的内容一致时则不会执行下面的Update语句,我们再来访问下刚才的地址查看控制台输出如下代码块所示:
Hibernate:
select
userbean0_.t_id as t_id1_0_0_,
userbean0_.t_address as t_addres2_0_0_,
userbean0_.t_age as t_age3_0_0_,
userbean0_.t_name as t_name4_0_0_,
userbean0_.t_pwd as t_pwd5_0_0_
from
t_user userbean0_
where
userbean0_.t_id=?
使用QueryDsl更新实体
下面我们来完全使用QueryDsl来更新实体,代码如下所示:
/**
* 使用QueryDsl更新会员信息
* @param userBean
*/
@RequestMapping(value = "/updateWithQueryDsl")
public String updateWithQueryDsl(UserBean userBean)
{
//querydsl查询实体
QUserBean _Q_user = QUserBean.userBean;
queryFactory
.update(_Q_user)//更新对象
//更新字段列表
.set(_Q_user.name,userBean.getName())
.set(_Q_user.address,userBean.getAddress())
.set(_Q_user.age,userBean.getAge())
.set(_Q_user.pwd,userBean.getPwd())
//更新条件
.where(_Q_user.id.eq(userBean.getId()))
//执行更新
.execute();
return "SUCCESS";
}
我们第一步先获取了QUserBean查询对象,并且通过JPAQueryFactory对象构建了update方法处理,而update的参数就是需要更新的查询实体,当然update方法内仅支持更新单个查询实体。
接下来我们就设置要更新的字段内容了,这里就是我们随心所欲控制了。需要更新哪些字段就设置对应字段更新的内容即可。
设置完成更新字段后需要设置更新的条件,不设置也是可以的,当然这里肯定跟原生SQL一样,不设置条件就更新表内全部的数据。
最后一步至关重要,如果不调用execute方法就不会执行更新操作。下面重启项目后访问地址:127.0.0.1:8080/updateWithQueryDsl?id=6&name=changeWithQueryDsl&age=24&address=山东济南&pwd=666666,界面输出内容如下图4所示:
javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:54) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
at com.querydsl.jpa.impl.JPAUpdateClause.execute(JPAUpdateClause.java:77) ~[querydsl-jpa-4.1.4.jar:na]
at com.yuqiyu.querydsl.sample.chapter3.controller.UserController.updateWithQueryDsl(UserController.java:76) ~[classes/:na]
.......
发现如果想执行update/delete方法时必须存在一个事务才可以,那我们修改更新方法添加事务注解@Transactional,重启项目再来访问我们之前的地址,界面输出内容如下图5所示:
Hibernate:
update
t_user
set
t_name=?,
t_address=?,
t_age=?,
t_pwd=?
where
t_id=?
使用SpringDataJPA删除实体信息
下面我们来看看SpringDataJPA删除实体信息时该怎么处理?代码如下所示:
/**
* 使用Jpa删除会员信息
* @param userBean
*/
@RequestMapping(value = "/deleteWithJpa")
public String deleteWithJpa(UserBean userBean)
{
//执行删除指定主键的值
userJPA.delete(userBean.getId());
return "SUCCESS";
}
控制台输出的SQL内容如下所示:
Hibernate:
delete
from
t_user
where
t_id=?
在编写删除方法之前我们想到了之前使用QueryDsl更新实体时需要添加事务,当然在删除的时候也是需要的所以我们编写删除方法时要注意