为什么JPA getReference()不能按预期工作?

时间:2018-05-08 06:04:34

标签: jpa spring-data-jpa

我对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()概念?或者缺少一些依赖?

1 个答案:

答案 0 :(得分:1)

你懒得加载实体,但是对该对象的任何方法调用都会使实际加载发生。 因此,当您setGender()时,它将触发选择查询。

如果您想在不选择实体(以及所有脏检查机制)的情况下进行更新,则必须执行dml样式查询(例如update ... set ... where ...),也称为批量操作

https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html#batch-direct