簡體   English   中英

當我所做的只是一個列表時,為什么Hibernate會刪除我的集合條目?

[英]Why is Hibernate deleting my collection entries when all I do is a list?

我似乎有一個相當奇怪的問題。 我在JSP中顯示用戶及其角色。 出於某種原因,角色僅在第一次加載頁面時顯示。 我刷新頁面,角色全部從數據庫中刪除!

我的設置是標准的Spring MVC,JPA + Hibernate(通過Spring Data)應用程序。 (Spring 3.2.x,Hibernate 4.1.8)

我有兩個實體 - UserRole ,如下所示(假設設置者和獲取者)

@Entity
public class User {
    @Id
    @GeneratedValue
    private int id;

    private String name;

    @ManyToMany
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles = new HashSet<>();
}

@Entity
public class Role {
    @Id
    private String id;

    private String name;
}

我有一個Spring Data存儲庫,它沒有定義任何額外的方法。

public interface UserRepository extends CrudRepository<User, Integer> { 
}

我有一個服務和一個控制器,其相關方法如下。

// service
@Transactional(readOnly = true)
public Iterable<User> findAll() {
    return userRepository.findAll();
}

// controller
@RequestMapping
public String showUsers(ModelMap model) {
    model.put("users", userService.findAll());

    return "admin/users";
}

在我的JSP中,我試圖顯示所有用戶和任何相關角色。

<c:forEach var="user" items="${users}">
    <tr>
        <td>${user.name}</td>
        <td>
           <c:forEach var="role" items="${user.roles}">
                ${role.name}
            </c:forEach>
        </td>
    </tr>
</c:forEach>

就像我之前說的那樣,我的user_role表中的記錄在渲染完這個頁面之后就會被刪除。

在為org.hibernate啟用DEBUG並啟用查詢日志記錄后,我在日志中找到了以下內容:

22:36:25 DEBUG Collection dereferenced: [com.adarshr.domain.User.roles#1] [Collections.java:76]
22:36:25 DEBUG Flushed: 0 insertions, 0 updates, 0 deletions to 2 objects [AbstractFlushingEventListener.java:117]
22:36:25 DEBUG Flushed: 0 (re)creations, 0 updates, 1 removals to 1 collections [AbstractFlushingEventListener.java:124]
22:36:25 DEBUG Deleting collection: [com.adarshr.domain.User.roles#1] [AbstractCollectionPersister.java:1124]
22:36:25 DEBUG 
    delete 
    from
        user_role 
    where
        user_id=? [SqlStatementLogger.java:104]
22:36:25 DEBUG Done deleting collection [AbstractCollectionPersister.java:1182]

很明顯這里有些可疑的東西。 為什么我的收藏品首先被解除引用?

這是我的JPA實體經理工廠定義。

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="mainDataSource" />
    <property name="packagesToScan" value="com.adarshr.domain" />
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <value>
            hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
            hibernate.format_sql=${hibernate.format.sql}
            hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
            hibernate.show_sql=${hibernate.show.sql}
            hibernate.enable_lazy_load_no_trans=true
        </value>
    </property>
</bean>

我錯過了一些明顯的東西嗎?

由於你發布的代碼似乎是正確的,我猜這里。

我建議的第一件事是刪除這個初始化(它似乎是刪除角色的唯一地方),這一般是一個好主意(見下面的評論)我認為可能會干擾hibernate.enable_lazy_load_no_trans=true已知在過去泄漏連接

 private Set<Role> roles = new HashSet<>();

如果您還使用mappedBy注釋ManyToMany關系的反面,則第二次嘗試將檢查是否以及更改。

第三次嘗試是如果急切加載集合修復了問題(加劇了enable_lazy_load_no_trans位置甚至更多),使用FetchType,Hibernate.initialize()無論你想要什么。

最后一個是擺脫enable_lazy_load_no_trans並使用OpenSessionInView

編輯:啊,最后一個,你可能*有這個bug(hibernate 4.1.8和4.1.9受影響): https//hibernate.onjira.com/browse/HHH-7971

因此,使用4.1.7可以獲得更好的結果(或者可能更糟)。

*其中可能的目的是:“您的情況非常相似,您被邀請將您的代碼作為測試用例發送到錯誤報告中”。

暫無
暫無

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

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