簡體   English   中英

java / Spring Hibernate不更新實體

[英]java/Spring Hibernate not updating entities

我已經閱讀並重新閱讀了SO和許多其他網站上的所有內容,但似乎無法弄清楚為什么我的更新對象沒有更新。

我正在做的基本概述:

  1. 服務層向DAO請求某些人員

  2. 回到人們的ArrayList從DB(DAO / @Repository)

  3. 服務層處理對象並將其添加到新的數組列表中

  4. 服務層將新列表傳遞回DAO以進行更新

  5. 沒什么更新

如果我在具有新值的對象中拋出一條日志消息,則說明這些子項已正確補水。 我沒有在代碼中出錯,只是不提交更改。

這是一些代碼:

PersonDAO 注釋為 @Repository

public void updatePeople(List<Person> people) {
    log.info("Updating " + people.size() + " people");
    try {
        Transaction tx = getCurrentSession().beginTransaction();
        for (Person person : people){
            getCurrentSession().saveOrUpdate(person);
        }
        getCurrentSession().flush();
        tx.commit();
        getCurrentSession().close();

    } catch (Exception e){
        log.error("Exception Updating all people " + e.toString());
        e.printStackTrace();
    }

}

public List<Person> getAssociatesByStoreId(String storeId) {
    try {

        List<Person> usersInStore = (List<Person>) getCurrentSession()
                .createCriteria(Person.class).createCriteria("store")
                .add(Restrictions.eq("storeId", storeId)).list();

        return usersInStore;
    } catch (Exception e) {
        log.error("exception in getAssociatesByStoreId ", e);
    }
    return null;
}

注釋為@Service的 PersonService-相關方法

/* I put the people into a map to do some other logic on them */
for (Person person : personDAO.getAllPeople()){
            personMap.put(person.getEmployeeId() + "-" + person.getStore().getStoreId(), person);
}

/*    
 I iterate a list creating new Person objects (based on some random stuff), 
 including saving any children entities (managementcodes and stores) that need to be created
 After I have created a new Person I attempt to find it in the map from above.  
 If I find it pull it out of the map and put it into an array list 
 that is eventually passed back into the DAO
*/

標注為@Entity

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;
}

編輯我在上面添加了兩組級聯類型注釋,仍然沒有運氣

編輯2更新了,以顯示主鍵定義有人踢我小狗之前請幫助我。 謝謝

可能是這種情況,您需要在ManyToOne批注上添加“ 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 {};

例如。

@ManyToOne(optional = true, cascade = {CascadeType.MERGE, CascadeType.PERSIST}, fetch = EAGER)

更新:如果您使用的是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>

DAO類:

@Repository
public class EventRepository {

@PersistenceContext
EntityManager entityManager;


@Transactional
public void persist(Event event) {
    entityManager.persist(event);
}
}

JPA實體對象主要有三種類型:

  1. 管理。 這些是JPA提供程序緩存的對象,因此JPA提供程序會跟蹤其狀態,並在事務提交時提交對其進行的任何更改。 這些是查詢時獲得的對象。 他們有一個數據庫ID。
  2. 新。 這些是尚未持久保存在數據庫中的實體對象。 JPA提供者對此一無所知。 他們沒有數據庫ID。
  3. 分離。 這些是曾經被管理的對象,但是不再是。 通常,將對象返回到事務外部的方法。 這些對象具有數據庫ID,但它們不是高速緩存的一部分,因此JPA提供者不知道它們。

為了保持一個實體與另一個實體之間的關系,必須對引用的實體進行管理。 有多種方法可以實現這一目標。

  1. 級聯。 從實體A到實體B的級聯意味着,當您在代碼中對實體A執行級聯操作時,JPA提供者將在實體B上執行相同的操作。如果將CascadeType.MERGE添加到關系中,並且具有實體引用分離的實體B,然后在實體A上執行merge() ,將首先引用實體B上的merge() ,從而對其進行管理。 然后存儲實體A時,它具有對托管B的引用,並且該關系得以保留。 (如果您還想持久保留對數據庫中尚未存在的對象的引用,則還添加CascadeType.PERSIST 。)
  2. 確保僅引用托管對象。 在事務內部,在存儲之前,加載引用的對象(托管對象)並將引用替換為托管對象。
  3. 擴大交易范圍。 這樣,引用的對象將永遠不會分離。

首先,請確保在這些ManyToOne批注上使用合適的CascadeType。

其次,entityManager /會話中的合並操作不會通過引用保持對象相等。 這意味着,在執行合並的更新情況下,檢查是否返回了不同的對象。 您應該始終使用保存操作的返回值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM