代码之家  ›  专栏  ›  技术社区  ›  Pavel

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

  •  1
  • Pavel  · 技术社区  · 7 年前

    我对jpa EntityManager有一个非常奇怪的问题。getReference()方法。我的@实体如下:

    @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 回复  |  直到 7 年前
        1
  •  1
  •   Zeromus    7 年前

    您可以延迟加载实体,但对该对象的任何方法调用都会导致实际加载。 所以当你 setGender() 它将触发select查询。

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

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