java/Spring Hibernate不更新实体

java/Spring Hibernate不更新实体,java,spring,hibernate,jpa,persistence,Java,Spring,Hibernate,Jpa,Persistence,我已经在SO和许多其他网站上反复阅读了这里的所有内容,但似乎不明白为什么我更新的对象没有更新 我所做工作的基本概述: 服务层为一些人请求DAO 从数据库(DAO/@Repository)返回人员的ArrayList 服务层操纵对象并将其添加到新的arraylist中 服务层将新列表传递回DAO进行更新 未更新任何内容 如果我在我的对象中抛出一条日志消息,并且该对象具有新的值,则表示孩子们已正确补水。代码中没有错误,只是没有提交更改 下面是一些代码: PersonDAO注释为@Repository

我已经在SO和许多其他网站上反复阅读了这里的所有内容,但似乎不明白为什么我更新的对象没有更新

我所做工作的基本概述:

  • 服务层为一些人请求DAO

  • 从数据库(DAO/@Repository)返回人员的ArrayList

  • 服务层操纵对象并将其添加到新的arraylist中

  • 服务层将新列表传递回DAO进行更新

  • 未更新任何内容

  • 如果我在我的对象中抛出一条日志消息,并且该对象具有新的值,则表示孩子们已正确补水。代码中没有错误,只是没有提交更改

    下面是一些代码:

    PersonDAO注释为@Repository

    注释为@Entity

    存储注释为实体(管理代码相同)

    /*字段+getter和setter*/
    @OneToMany(fetch=FetchType.LAZY,mappedBy=“store”,cascade={CascadeType.MERGE,CascadeType.PERSIST})
    @LazyCollection(LazyCollectionOption.EXTRA)
    @杰索尼奥雷
    公共集合getPersons(){
    将本文件归还给所有人;
    }
    
    EDIT我在上面添加了两组级联类型注释,但仍然没有成功

    编辑2更新以显示主键定义 在我踢小狗之前,请有人帮帮我。
    谢谢

    在这种情况下,您可能需要在manytone注释上设置“cascade={CascadeType.MERGE,CascadeType.PERSIST}”。默认行为不会将任何内容级联到关联对象

     /**
     * (Optional) The operations that must be cascaded to
     * the target of the association.
     *
     * <p> By default no operations are cascaded.
     */
    CascadeType[] cascade() default {};
    
    更新: 如果您使用的是spring托管事务管理器,并且可以自由使用注释驱动的事务划分,那么您可以尝试spring@Transactional注释,而不是手动启动事务和提交/刷新

    我有以下设置:

    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="persistenceUnitName" value="persistenceUnit"/>
        <property name="dataSource" ref="local-dataSource"/>
        <property name="packagesToScan" value="X"/>
        <property name="persistenceXmlLocation" value="classpath:persistence.xml"/>
    </bean>
    

    首先,确保在这些多通注释上使用fitting CascadeType


    其次,entityManager/session中的合并操作不会通过引用保持对象相等。这意味着,在执行合并的更新情况下,检查是否返回了不同的对象。您应该始终使用保存操作的返回值。

    使用JPA的实体对象主要有三种类型:

  • 管理。这些是JPA提供者缓存的对象,因此JPA提供者跟踪它们的状态,并在事务提交时提交对它们所做的任何更改。这些是查询时得到的对象。他们有一个数据库id
  • 新的。这些是尚未在数据库中持久化的实体对象。JPA提供商对它们一无所知。它们没有数据库id
  • 超脱的。这些对象过去是被管理的,但现在不再是。通常,返回到事务外部的方法的对象。这些对象有一个数据库id,但它们不是缓存的一部分,因此JPA提供者不知道它们
  • 为了保持一个实体和另一个实体之间的关系,必须管理被引用的实体。实现这一点有多种方法

  • 瀑布。从实体A到实体B的级联意味着当您在代码中对实体A执行级联操作时,JPA提供程序将对实体B执行相同的操作。如果您向关系添加
    CascadeType.MERGE
    ,并让实体A引用分离的实体B,则执行
    MERGE()实体A上的
    将首先到实体B上的合并(),使其处于管理状态。当实体A随后被存储时,它具有对托管B的引用,并且关系被持久化。(如果还希望持久化对数据库中不存在的对象的引用,请同时添加
    CascadeType.persist
    。)
  • 确保仅引用托管对象。在事务内部,加载引用对象(托管对象)并用托管对象替换引用,然后再存储
  • 扩大你的交易范围。这样,被引用的对象将永远不会分离

  • 根据您和其他评论,我在我的多通关系中添加了以下内容。optional=true,cascade={CascadeType.MERGE,CascadeType.PERSIST}我已将CascadeType.MERGE添加到所有子依赖项中。我可以看到使用session.contains(person)时,此实体不受会话管理。根据你的描述,我相信这会使我的物体分离。如何重新连接它们?合并->使用返回的对象->保存或更新?(正在尝试)当我在保存或更新中使用合并返回的person对象时,我得到:非法尝试将集合与两个打开的会话关联不确定这是否更好或更糟这是怎么标记的?这是一个非常笼统的答案,而不是针对手头的问题。@JamesB我不同意,这是对可能导致问题的原因的详细解释,以及3种可能的解决方案。@Puttzy从当时提供的内容来看,我认为Hibernate的
    SAVE\u UPDATE
    cascade应该可以做到这一点,无需更改Dao代码。但是删除
    Person
    getManagementCode
    上的
    @LazyCollection
    ,该注释是针对集合(@*ToMany)的,而这不是。修订号是否在更新时增加?在您再次尝试保存这些Person对象之前,它们是否已被更改?如果您有任何主键冲突,这些可能会被宣布为一个错误。这也将有助于了解有关问题的更多代码。如何为Person定义主键?我的更新中没有出现冲突或异常。至于我在操作什么…现在我已经对它进行了简化,以更新first-name属性。当我输出之前和之后的人员obejct时,我可以看到差异伟大的建议bu
    private int personid;
    private String firstName;
    private String lastName;
    private Store store;
    private ManagementCode managementCode;
    
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "personid", unique = true, nullable = false)
    public int getPersonid() {
        return this.personid;
    }
    
        /*a bunch of getters and setters*/
    @ManyToOne(fetch = FetchType.LAZY, optional = true, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    @org.hibernate.annotations.Cascade( {org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST})
    @LazyCollection(LazyCollectionOption.EXTRA)
    @JoinColumn(name = "managementlevel", nullable = true)
    public ManagementCode getManagementCode() {
        return this.managementCode;
    }
    
    @ManyToOne(fetch = FetchType.LAZY, optional = true, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    //  @org.hibernate.annotations.Cascade( {org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.PERSIST})
    @JoinColumn(name = "storeid", nullable = false)
    public Store getStore() {
        return this.store;
    }
    
    /*fields + getters and setter */
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "store", cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    @LazyCollection(LazyCollectionOption.EXTRA)
    @JsonIgnore 
    public Set<Person> getPersons() {
        return this.persons;
    }
    
     /**
     * (Optional) The operations that must be cascaded to
     * the target of the association.
     *
     * <p> By default no operations are cascaded.
     */
    CascadeType[] cascade() default {};
    
    @ManyToOne(optional = true, cascade = {CascadeType.MERGE, CascadeType.PERSIST}, fetch = EAGER)
    
    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="persistenceUnitName" value="persistenceUnit"/>
        <property name="dataSource" ref="local-dataSource"/>
        <property name="packagesToScan" value="X"/>
        <property name="persistenceXmlLocation" value="classpath:persistence.xml"/>
    </bean>
    
    @Repository
    public class EventRepository {
    
    @PersistenceContext
    EntityManager entityManager;
    
    
    @Transactional
    public void persist(Event event) {
        entityManager.persist(event);
    }
    }