[英]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)
我有兩個實體 - User
和Role
,如下所示(假設設置者和獲取者)
@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.