要获得答案,请向下滚动到此内容的末尾…
基本问题与多次询问相同。我有一个带有两个POJO事件和用户的简单程序-一个用户可以拥有多个事件。
@Entity
@Table
public class Event {
private Long id;
private String name;
private User user;
@Column
@Id
@GeneratedValue
public Long getId() {return id;}
public void setId(Long id) { this.id = id; }
@Column
public String getName() {return name;}
public void setName(String name) {this.name = name;}
@ManyToOne
@JoinColumn(name="user_id")
public User getUser() {return user;}
public void setUser(User user) {this.user = user;}
}
用户:
@Entity
@Table
public class User {
private Long id;
private String name;
private List<Event> events;
@Column
@Id
@GeneratedValue
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@Column
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@OneToMany(mappedBy="user", fetch=FetchType.LAZY)
public List<Event> getEvents() { return events; }
public void setEvents(List<Event> events) { this.events = events; }
}
注意:这是一个示例项目。我 真的 很想在这里使用Lazy抓取。
现在我们需要配置spring和hibernate,并有一个简单的basic-db.xml用于加载:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" scope="thread">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.1.34:3306/hibernateTest" />
<property name="username" value="root" />
<property name="password" value="" />
<aop:scoped-proxy/>
</bean>
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread">
<bean class="org.springframework.context.support.SimpleThreadScope" />
</entry>
</map>
</property>
</bean>
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" scope="thread">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
<value>data.model.User</value>
<value>data.model.Event</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
<aop:scoped-proxy/>
</bean>
<bean id="myUserDAO" class="data.dao.impl.UserDaoImpl">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
<bean id="myEventDAO" class="data.dao.impl.EventDaoImpl">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
</beans>
注意:我玩过CustomScopeConfigurer和SimpleThreadScope,但是并没有改变任何东西。
我有一个简单的dao-impl(仅粘贴userDao-EventDao几乎相同-除了没有“ listWith”函数:
public class UserDaoImpl implements UserDao{
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
@SuppressWarnings("unchecked")
@Override
public List listUser() {
return hibernateTemplate.find("from User");
}
@Override
public void saveUser(User user) {
hibernateTemplate.saveOrUpdate(user);
}
@Override
public List listUserWithEvent() {
List users = hibernateTemplate.find("from User");
for (User user : users) {
System.out.println("LIST : " + user.getName() + ":");
user.getEvents().size();
}
return users;
}
}
我正在收到org.hibernate.LazyInitializationException-
无法延迟初始化角色集合:data.model.User.events,没有会话或与 user.getEvents()。size() 一起关闭的会话;
最后但并非最不重要的是我使用的Test类:
public class HibernateTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("basic-db.xml");
UserDao udao = (UserDao) ac.getBean("myUserDAO");
EventDao edao = (EventDao) ac.getBean("myEventDAO");
System.out.println("New user...");
User user = new User();
user.setName("test");
Event event1 = new Event();
event1.setName("Birthday1");
event1.setUser(user);
Event event2 = new Event();
event2.setName("Birthday2");
event2.setUser(user);
udao.saveUser(user);
edao.saveEvent(event1);
edao.saveEvent(event2);
List users = udao.listUserWithEvent();
System.out.println("Events for users");
for (User u : users) {
System.out.println(u.getId() + ":" + u.getName() + " --");
for (Event e : u.getEvents())
{
System.out.println("\t" + e.getId() + ":" + e.getName());
}
}
((ConfigurableApplicationContext)ac).close();
}
}
这是例外:
1621 [main]错误org.hibernate.LazyInitializationException-无法延迟初始化角色集合:data.model.User.events,没有会话或会话被关闭
org.hibernate.LazyInitializationException:无法延迟初始化角色集合:data.model.User.events,没有会话或会话被关闭
在org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
在org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
在org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
在org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
在data.dao.impl.UserDaoImpl.listUserWithEvent(UserDaoImpl.java:38)
在HibernateTest.main(HibernateTest.java:44)
线程“主要” org.hibernate.LazyInitializationException中的异常:无法延迟初始化角色集合:data.model.User.events,没有会话或会话被关闭
在org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
在org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
在org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
在org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
在data.dao.impl.UserDaoImpl.listUserWithEvent(UserDaoImpl.java:38)
在HibernateTest.main(HibernateTest.java:44)
事情尝试了但没有用:
分配一个threadScope并使用beanfactory(我使用了“ request”或“ thread”-没有区别):
//作用域的东西
范围threadScope = new SimpleThreadScope();
ConfigurableListableBeanFactory beanFactory = ac.getBeanFactory();
beanFactory.registerScope(“ request”,threadScope);
ac.refresh();
…
通过从Deo获取会话对象来设置事务:
…
交易tx =((UserDaoImpl)udao).getSession()。beginTransaction();
tx.begin();
用户= udao.listUserWithEvent();
…
在listUserWithEvent()中获取交易
公共列表listUserWithEvent(){
SessionFactory sf = hibernateTemplate.getSessionFactory();
会话s = sf.openSession();
交易tx = s.beginTransaction();
tx.begin();
列出用户= hibernateTemplate.find(“来自用户”);
对于(用户用户:用户){
System.out.println(“ LIST:” + user.getName()+“:”);
user.getEvents()。size();
}
tx.commit();
回头客;
}
到目前为止,我真的没有主意。另外,使用listUser或listEvent也可以正常工作。
向前一步:
多亏蒂埃里(Thierry),我才迈出了一步。我创建了MyTransaction类,并在那里进行所有工作,从春季开始获取所有内容。新的主体如下所示:
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("basic-db.xml");
// getting dao
UserDao udao = (UserDao) ac.getBean("myUserDAO");
EventDao edao = (EventDao) ac.getBean("myEventDAO");
// gettting transaction template
TransactionTemplate transactionTemplate = (TransactionTemplate) ac.getBean("transactionTemplate");
MyTransaction mt = new MyTransaction(udao, edao);
transactionTemplate.execute(mt);
((ConfigurableApplicationContext)ac).close();
}
不幸的是,现在有一个空指针异常@:user.getEvents()。size();。(在daoImpl中)。
我知道它不应该为null(无论是从控制台的输出还是从数据库布局)。
这是控制台的更多信息(我检查过user.getEvent()== null并显示“ EVENT is NULL”):
新的用户...
休眠:插入用户(名称)值(?)
休眠:插入用户(名称)值(?)
休眠:插入事件(名称,用户ID)值(?,?)
休眠:插入事件(名称,用户ID)值(?,?)
休眠:插入事件(名称,用户ID)值(?,?)
列出用户:
休眠:从用户user0_中选择user0_.id作为id0_,将user0_.name作为name0_
1:用户1
2:用户2
列出事件:
休眠:从事件event0_中选择event0_.id作为id1_,event0_.name作为name1_,event0_.user_id作为user3_1_
1:User1的1:Birthday1
2:1的User1的生日2
3:为2:User2结婚
休眠:从用户user0_中选择user0_.id作为id0_,将user0_.name作为name0_
用户活动
1:用户1-
EVENT为NULL
2:用户2-
EVENT为NULL
您可以从http://www.gargan.org/code/hibernate-
test1.tgz获得示例项目(这是一个eclipse /
maven项目)
解决方案(适用于控制台应用程序)
对于此问题,实际上有两种解决方案-取决于您的环境:
对于控制台应用程序,您需要一个事务模板来捕获实际的db逻辑并处理事务:
public class UserGetTransaction implements TransactionCallback{
public List users;
protected ApplicationContext context;
public UserGetTransaction (ApplicationContext context) {
this.context = context;
}
@Override
public Boolean doInTransaction(TransactionStatus arg0) {
UserDao udao = (UserDao) ac.getBean("myUserDAO");
users = udao.listUserWithEvent();
return null;
}
}
您可以通过以下方式使用此功能:
TransactionTemplate transactionTemplate = (TransactionTemplate) context.getBean("transactionTemplate");
UserGetTransaction mt = new UserGetTransaction(context);
transactionTemplate.execute(mt);
为了使它起作用,您需要为spring定义模板类(即,在basic-db.xml中):
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
另一个(可能的)解决方案
谢谢安迪
PlatformTransactionManager transactionManager = (PlatformTransactionManager) applicationContext.getBean("transactionManager");
DefaultTransactionAttribute transactionAttribute = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED);
transactionAttribute.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
TransactionStatus status = transactionManager.getTransaction(transactionAttribute);
boolean success = false;
try {
new UserDataAccessCode().execute();
success = true;
} finally {
if (success) {
transactionManager.commit(status);
} else {
transactionManager.rollback(status);
}
}
解决方案(针对servlet)
Servlet并不是什么大问题。当您拥有servlet时,您可以简单地在函数的开头启动并绑定一个事务,并在结束时再次取消绑定:
public void doGet(...) {
SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
// Your code....
TransactionSynchronizationManager.unbindResource(sessionFactory);
}
我认为您不应该使用休眠会话事务方法,而让spring这样做。
将此添加到您的春季会议:
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager"/>
</bean>
然后我将修改您的测试方法以使用spring事务模板:
public static void main(String[] args) {
// init here (getting dao and transaction template)
transactionTemplate.execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus status) {
// do your hibernate stuff in here : call save, list method, etc
}
}
}
附带说明一下,@OneToMany关联默认情况下是惰性的,因此您无需将其注释为惰性。(@ * ToMany默认为LAZY,@ * ToOne默认为EAGER)
编辑:从休眠的角度来看,这就是现在正在发生的事情:
…与所有保存操作相同…
然后加载所有用户(“来自用户”查询)
那时,hibernate看到它在其会话中已经有该对象,因此丢弃从请求中获得的对象,然后从会话中返回该对象。
以下是增强代码的一些要点:
因此,要解决上述问题,可以在一个事务中进行保存,而在另一事务中进行加载:
public static void main(String[] args) {
// init here (getting dao and transaction template)
transactionTemplate.execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus status) {
// save here
}
}
transactionTemplate.execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus status) {
// list here
}
}
}
或设置双方:
...
event1.setUser(user);
...
event2.setUser(user);
...
user.setEvents(Arrays.asList(event1,event2));
...
(也别忘了解决上面的代码增强点,设置不列出,键入集合)
问题内容: 要获得答案,请向下滚动到此内容的结尾… 基本问题与多次询问相同。我有一个带有两个POJO事件和用户的简单程序-一个用户可以拥有多个事件。 用户: 注意:这是一个示例项目。我 真的 很想在这里使用Lazy抓取。 现在我们需要配置spring和hibernate,并有一个简单的basic-db.xml用于加载: 注意:我玩过CustomScopeConfigurer和SimpleThrea
问题内容: 我有下一个错误: 我的实体: 我有一个服务班: 我从另一种服务方法调用服务: 但是,当我试图调用这个方法我收到线异常,当我打电话时,也会发生同样的异常上。我已经检查了事务管理器,并且配置正确,并且此步骤中存在事务。另外,我已经检查了关于与此异常相关的stackoverflow的大量答案,但没什么用。 可能是什么原因造成的? 问题答案: 看来模型是一个独立的实体。 尝试合并并在合并实例上
问题内容: 对数据库有以下查询: 在获取employee.address.street,employee.address.houseNumber或employee.address.city时,它将失败,但以下情况除外: 员工映射: 地址映射: 对于其他类(办公室,公司等),这是绝对正常的。如果注释,则在jsp应用程序中加载地址字段的行将正常工作。怎么了?顺便说一下,尽管有异常,它仍显示有关js
问题内容: 好的,我在正在处理的应用程序中收到上述异常。我正在使用JPA并hibernate。这是堆栈跟踪: 调试时,我注意到它似乎来自Form实体中的部分代码: “ fields.isEmpty()”部分将异常向上抛出。 据我所读,这应该可以通过设置要热切获取的集合来解决。我认为问题是字段集合。但是… 它已经很热闹。这样做是为了解决开发早期遇到的另一个问题。 可能是什么问题呢? 添加: Form
问题内容: 当我按如下方式调用session.begin事务方法时: 然后我得到以下异常消息 造成此错误的原因是什么? 问题答案: 更新: 我想调用并不能保证该会话实际上是打开的。第一次,您应该使用 代替。该建议实际上与您找到的页面一致。 之前: 根据到目前为止的可用信息,我们可以得出结论,错误的原因是会话未打开;-)
我正在使用JPA(Hibernate 4 . 3 . 3作为持久性提供者)和Spring (3.2.2),我所有的字段都加载得很好,但是当我试图访问我的集合时,它抛出了错误- 当我调试这个时,我的实体类中定义的每个集合都有错误- 我尝试使用collection.size()和Hibernate.initialize(),但都不起作用。在Internet上搜索时,我发现扩展Persitence将解决