尝试从对象中的延迟提取列表中删除时出现问题。我有一个User对象和一个Event对象。用户可以参加活动,并将其存储在两个对象中。
用户对象:
@Entity
@Table(name = "User")
public class User implements Serializable {
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "attendingUsers")
private List<Event> attendingEvents = new ArrayList<Event>();
}
Event对象:
@Entity
@Table(name = "Event")
public class Event implements Serializable {
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "Event_User",
joinColumns = @JoinColumn(name = "event_id", nullable = false, updatable = false),
inverseJoinColumns = @JoinColumn(name = "user_id", nullable = false, updatable = false))
List<User> attendingUsers = new ArrayList<User>();
}
当然,这些列表中有Setters和Getters。现在我想实现以用户身份无人参与这些事件的可能性。因此我尝试了以下方法:
public void unattend(Event e, User u){
List<User> attendingUsers = getAttendingUsers(e.getId());
List<Event> attendingEventsForUser = userService.getEvents(u.getId());
if(attendingUsers.contains(u)){
e.getAttendingUsers().clear();
u.getAttendingEvents().clear();
attendingUsers.remove(u);
attendingEventsForUser.remove(e);
e.getAttendingUsers().addAll(attendingUsers);
u.getAttendingEvents().addAll(attendingEventsForUser);
update(e);
userDAO.update(u);
}
}
我得到的例外情况如下:
07.01.2014 15:52:20 org.apache.catalina.core.StandardWrapperValve调用 SCHWERWIEGEND:Servlet [appServlet]的Servlet.service()与路径[/ tripitude]的上下文 抛出异常[请求处理失败;嵌套异常是org.hibernate.LazyInitializationException:懒得初始化一个角色集合:ac.tuwien.ase08.tripitude.entity.Event.attendingUsers,无法初始化代理 - 没有会话]的根本原因 org.hibernate.LazyInitializationException:懒得初始化一个角色集合:ac.tuwien.ase08.tripitude.entity.Event.attendingUsers,无法初始化代理 - 没有Session at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566) at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186) at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545) 在org.hibernate.collection.internal.PersistentBag.clear(PersistentBag.java:381) at ac.tuwien.ase08.tripitude.service.EventService.unattend(EventService.java:76) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在java.lang.reflect.Method.invoke(Method.java:597) 在org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 在org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.transaction.interceptor.TransactionInterceptor $ 1.proceedWithInvocation(TransactionInterceptor.java:96) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 在org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 在org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 在$ Proxy64.unattend(未知来源)
虽然我正在使用方法来确保执行延迟提取:
public List<User> getAttendingUsers(Long id){
Query query = sessionFactory.getCurrentSession().createQuery(
"SELECT u FROM User AS u LEFT JOIN u.attendingEvents AS ae WHERE ae.id = :id");
query.setParameter("id", id);
List<User> l = (List<User>)query.list();
return l;
}
和另一个:
@Override
public List<Event> getEvents(Long id) {
Query query = sessionFactory.getCurrentSession().createQuery(
"SELECT e FROM Event AS e LEFT JOIN e.attendingUsers AS au WHERE au.id = :id");
query.setParameter("id", id);
List<Event> l = (List<Event>)query.list();
return l;
}
我正在考虑使用查询进行删除,但是我再也没有想到正确的代码:/
非常感谢帮助,谢谢!
编辑:我刚刚意识到我一直在调用.getAttendingUsers()
和.getAttendingEvents()
而我还没有实际初始化这两个。所以现在我跳过那部分并将我的代码更新为:
public void unattend(Event e, User u){
Query query = sessionFactory.getCurrentSession().createQuery(
"SELECT u FROM User AS u LEFT JOIN FETCH u.attendingEvents AS ae WHERE ae.id = :id");
query.setParameter("id", e.getId());
List<User> attendingUsers = (List<User>)query.list();
Query query2 = sessionFactory.getCurrentSession().createQuery(
"SELECT e FROM Event AS e LEFT JOIN FETCH e.attendingUsers AS au WHERE au.id = :id");
query2.setParameter("id", u.getId());
List<Event> attendingEventsForUser = (List<Event>)query2.list();
if(attendingUsers.contains(u)){
attendingUsers.remove(u);
attendingEventsForUser.remove(e);
e.setAttendingUsers(attendingUsers);
u.setAttendingEvents(attendingEventsForUser);
update(e);
userDAO.update(u);
}
}
我得到一个新例外:
07.01.2014 16:51:34 org.apache.catalina.core.StandardWrapperValve调用 SCHWERWIEGEND:Servlet [appServlet]的Servlet.service()在路径[/ tripitude]的上下文中引发异常[请求处理失败;嵌套异常是org.hibernate.NonUniqueObjectException:具有相同标识符值的另一个对象已与会话关联:[ac.tuwien.ase08.tripitude.entity.Event#3]]具有根本原因 org.hibernate.NonUniqueObjectException:具有相同标识符值的另一个对象已与会话关联:[ac.tuwien.ase08.tripitude.entity.Event#3] at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:697) 在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:296) 在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:241) 在org.hibernate.event.internal.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:55) 在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90) 在org.hibernate.internal.SessionImpl.fireUpdate(SessionImpl.java:786) 在org.hibernate.internal.SessionImpl.update(SessionImpl.java:778) 在org.hibernate.internal.SessionImpl.update(SessionImpl.java:774) at ac.tuwien.ase08.tripitude.dao.HibernateDAO.update(HibernateDAO.java:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在java.lang.reflect.Method.invoke(Method.java:597) 在org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 在org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.transaction.interceptor.TransactionInterceptor $ 1.proceedWithInvocation(TransactionInterceptor.java:96) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 在org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 在org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 在$ Proxy63.update(未知来源) at ac.tuwien.ase08.tripitude.service.EventService.update(EventService.java:41) at ac.tuwien.ase08.tripitude.service.EventService.unattend(EventService.java:84)
答案 0 :(得分:0)
您正在尝试访问事务之外的惰性集合。您可以使用@Transactional
注释相关方法,也可以使用fetch join:
SELECT e FROM Event AS e LEFT JOIN FETCH e.attendingUsers ...
在交易中工作通常更可取,因为只有在需要时才会获取相关实体。
编辑:Exception
可能来自“无人参与”方法中的if
子句,您可以在其中访问列表:e.getAttendingUsers()
。我会将它从控制器移动到事务服务,如EventService
。