- Oracle TopLink Essentials v1 Build 48
- Hibernate Core v3.2.6.ga
- Hibernate Annotations v3.3.1.GA
- Hibernate Entity Manager v3.3.2.GA
- Spring Framework v2.5.5 LocalContainerEntityManagerFactoryBean
User和Address為bidirectional one-to-many的關係,在User有以下的property acccessor:
@OneToMany(cascade={CascadeType.REFRESH, CascadeType.REMOVE}, fetch=FetchType.EAGER, mappedBy="user")
public Set<Address> getAddresses() {
return Addresses;
}
在Address有以下的property acccessor:
先persist User之後,persist Address時會丟出以下的Exception:
@ManyToOne(cascade={CascadeType.ALL}, optional=false)
@JoinTable(name="address_user")
public User getUser() {
return this.user;
}
原因:這是由於「CascadeType.ALL」包含「CascadeType.PERSIST」,導致persist Address時傳播了這個動作到User,使得persisted User重複地被persist。
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: User
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:637)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist (AbstractEntityManagerImpl.java:226)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:358)
at $Proxy24.persist(Unknown Source)
...
解決方法:修改Address的@ManyToOne annotation,移除cascade={CascadeType.ALL}。只要cascade不包含CascadeType.PERSIST就不會丟出Exception,例如
@ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH, CascadeType.REMOVE}, optional=false)
0 意見:
張貼留言