我对jpa EntityManager.getReference()方法有一个非常奇怪的问题。我的@Entity如下:
@Entity
@Table(name="people")
public class Person {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@Id
private long id;
@Column(name = "full_name")
private String fullName;
@Column(name = "location")
private String location;
@Column(name = "gender")
private String gender;
//getters and setters are omitted
Maven依赖项:
spring-boot-starter-web 2.0.1.RELEASE
jackson-dataformat-xml 2.9.5
spring-boot-starter-data-jpa 2.0.1.RELEASE
h2 1.4.197
所以发布时:
@Autowired
private PersonRepository pr;
@Transactional(propagation=Propagation.REQUIRED)
public void fetch() {
Person per = pr.getOne(1L);
per.setGender("male");
}
(getOne()只委托给底层的EM getReference()) 我期待以下行为:
update
people
set
gender=?,
where
id=?
但实际上我得到了以下内容:
o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name []: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@577a117e]
o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
o.s.orm.jpa.JpaTransactionManager : Participating in existing transaction
org.hibernate.SQL :
select
person0_.id as id1_5_0_,
person0_.full_name as full_nam2_5_0_,
person0_.gender as gender3_5_0_,
person0_.location as location4_5_0_
from
people person0_
where
person0_.id=?
o.s.orm.jpa.JpaTransactionManager : Triggering beforeCommit synchronization
o.s.orm.jpa.JpaTransactionManager : Triggering beforeCompletion synchronization
o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[domain.Person#1]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
org.hibernate.SQL :
update
people
set
full_name=?,
gender=?,
location=?
where
id=?
o.s.orm.jpa.JpaTransactionManager : Triggering afterCommit synchronization
o.s.orm.jpa.JpaTransactionManager : Triggering afterCompletion synchronization
o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[domain.Person#1]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] after transaction
2018-05-08 08:53:30.238 DEBUG 684 --- [nio-8080-exec-5] o.s.orm.jpa.EntityManagerFactoryUtils : Closing JPA EntityManager
也许我误解了getReference()概念?或者缺少一些依赖?
答案 0 :(得分:1)
你懒得加载实体,但是对该对象的任何方法调用都会使实际加载发生。
因此,当您setGender()
时,它将触发选择查询。
如果您想在不选择实体(以及所有脏检查机制)的情况下进行更新,则必须执行dml
样式查询(例如update ... set ... where ...
),也称为批量操作
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html#batch-direct