到目前为止,我使用了经典的Hibernate和#34; Session"对象而不使用JPA EntityManager。现在我通过激活服务" org.hibernate.jpa.event.spi.JpaIntegrator"来介绍JPA Listener/callback支持。在我的META-INF。
之后我在电话会议期间得到" session.saveOrUpdate()"这个错误。我添加的监听器是在另一个类上,如果我删除那里的" EntityListeners" JPA注释,错误仍然出现。
java.lang.IllegalArgumentException: Removing a detached instance Attribute#233800
at org.hibernate.jpa.event.internal.core.JpaDeleteEventListener.performDetachedEntityDeletionCheck(JpaDeleteEventListener.java:69)
没有这个JPA Listener激活它工作正常。
我的代码是从父项中删除对象(已分离 - 在事务外部),然后尝试使用新事务保存父项。孩子由父母拥有,所有的变化都应该级联?那么我需要做什么或者这是一个Hibernate的Bug?
我正在使用Hibernate v4.3.10
我添加的监听器是在另一个类上,如果我删除了注释,错误仍然会出现。
执行代码
Model model = modelDAO.getModelByCode("1234567");
model.removeAttribute("Description");
modelDAO.saveModel(model);
ModelDAO的实施
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
protected void beginTransaction() {
Session session = getSession();
Transaction transaction = session.getTransaction();
if (!transaction.isActive()) {
transaction.begin();
}
}
protected void handleTransaction() {
if (!bulkHandling) {
commitTransaction();
}
}
protected void commitTransaction() {
Session session = getSession();
Transaction transaction = session.getTransaction();
if (transaction.isActive()) {
transaction.commit();
}
}
protected void saveObject(Object obj) {
if(obj != null) {
try {
Session session = getSession();
beginTransaction();
if (!session.contains(obj)) {
session.saveOrUpdate(obj);
}
handleTransaction();
} catch (Exception ex) {
logger.error(ex.getMessage(),ex);
rollbackTransaction();
throw new HandledOneERPException(ex);
}
}
}
模特&映射
@Entity
public class Model extends AbstractERPEntity implements Translateable {
@OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval=true)
@JoinTable(name = "model_attributes", joinColumns = @JoinColumn(name = "model_id"), inverseJoinColumns = @JoinColumn(name = "attribute_id"))
@MapKey(name = "name")
private Map<String, Attribute<?>> attributes = new HashMap<String, Attribute<?>>();
完整堆栈跟踪
java.lang.IllegalArgumentException: Removing a detached instance ch.megloff.one.erp.model.attribute.Attribute#233800
at org.hibernate.jpa.event.internal.core.JpaDeleteEventListener.performDetachedEntityDeletionCheck(JpaDeleteEventListener.java:69) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:106) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:965) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.internal.SessionImpl.delete(SessionImpl.java:909) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.engine.internal.Cascade.deleteOrphans(Cascade.java:437) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:410) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:86) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:375) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:349) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:244) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:109) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:684) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:676) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:671) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_65]
at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_65]
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:356) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
at com.sun.proxy.$Proxy70.saveOrUpdate(Unknown Source) ~[?:?]
at ch.megloff.common.dao.AbstractHibernateDAO.saveObject(AbstractHibernateDAO.java:261) [classes/:?]
答案 0 :(得分:0)
我花了几个小时但是我没有使用JPA Listener&#34; org.hibernate.jpa.event.spi.JpaIntegrator&#34;。在研究了以下链接后
我得出的结论是,这最像是一个Hibernate的错误,因为&#34; saveOrUpdate()&#34;如果我不使用&#34; JpaIntegrator&#34;它应该处理这种情况。东西。我也试过Hibernate 4.3.11,同样的问题。
我的解决方案是使用特殊的JPA Listener激活Hibernate Event Listener
e.g。
@Component
@Log4j2
public class HibernateEventListener implements PostCommitDeleteEventListener {
@Autowired
@Qualifier("hibernateOneERPSessionFactory")
private SessionFactory sessionFactory;
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Autowired
private TranslationDAO translationDAO;
@PostConstruct
public void registerListeners() {
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.setAwaitTerminationSeconds(Integer.MAX_VALUE);
final EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory)
.getServiceRegistry().getService(EventListenerRegistry.class);
registry.appendListeners(EventType.POST_COMMIT_DELETE, this);
}
@Override
public void onPostDelete(PostDeleteEvent event) {
Object obj = event.getEntity();
if(obj instanceof Translateable) {
Translateable translateable = (Translateable)obj;
if (translateable.hasTranslation()) {
Runnable task = new Runnable() {
public void run() {
translationDAO.deleteUnusedTranslations();
}
};
taskExecutor.initialize();
taskExecutor.execute(task);
taskExecutor.shutdown();
}
}
}
}