最关键一句
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>但是,另一个没有测试过,就是网页对 对象的延迟加载,下面第二种配置以后可以试试
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <!-- 指定数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 指定Entity实体类包路径 --> <property name="packagesToScan"> <list> <value>com.xxx.xxx.jpadomain</value> </list> </property> <!-- 指定JPA属性;如Hibernate中指定是否显示SQL的是否显示、方言等 --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <!-- 是否生成ddl文件 --> <property name="generateDdl" value="true"/> <!-- 是否展示sql --> <property name="showSql" value="false"/> <!-- 必要的数据库库使用的详细信息 --> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/> <!-- mysql,自行选择 --> <property name="database" value="MYSQL"/> </bean> </property> <property name="jpaProperties"> <props> <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy </prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.enable_lazy_load_no_trans">true</prop> </props> </property> </bean>
第二种:
Sping和hibernate在去年年底都发布了新的版本,现在我做的项目都将最新版本的spring和Hibernate引入了,使用效果良好。不过最近遇到了一个以前没有遇到的问题——实体的延时加载。
对于关系型数据库,表与表之间的某些字段是通过一对多、多对一或者是多对多的关系来维护的,因此Hibernate引入了延迟加载的优化方法。例如一个雇员,包含姓名,性别等等信息,而最重要的就是所属部门。这些员工与部门就存在着多对一的关系。当我从数据库中获取到雇员的时候,假如没有延迟加载优化,那么雇员的信息以及部门相关的属性都会一并加载下来,假如一个部门信息内再有关联的其它信息,那就会占用很多时间来查询。然而有时候,我们获取雇员仅仅是为了显示一下姓名。
上面是针对延迟加载应用场景的一个表述,下面是我的代码:
首先是部门表的关联代码
接下来是雇员的关联代码
这里,雇员表的部门列我使用了延迟加载配置。其它配置都是JPA中普通的注解配置。列名称与属性名称相同时就不用配置@Column注解的name属性。
然后就按部就班地写了表操作的服务及实现。这里就不多说了。
接下来在Spring MVC中标注了@Controller的类的方法中尝试按照雇员id来获取雇员信息:
当我尝试访问http://localhost/show.do?empId=1的时候发现出现了如下的错误:
很明显是由于jpa的entityManager将事务关闭了,因此延迟加载时找不到存在的会话来运行接下来的自动查询。
在网上找了很多资料,最终找到了解决办法:
首先在配置JPA的EntityManager配置文件中加入如下配置:
然后在配置Servlet的配置文件中更改支持@RequestMapping注解的配置:
原来的多数配置都是这样的:
现在我们为这个默认的注解处理映射加入视图内拦截器来自动生成会话:
好了,加入了以上配置后,再访问同样的接口,发现问题解决了。如果你在使用JPA的时候打开了show_sql选项,你会看到执行了两条JPQL语句。
2014年11月14日补充:今天发现按照上述配置后仍然可能在懒加载时无法获取关联对象。经过检查,是由于没有加入事务造成的。首先要在spring配置文件中加入事务注解支持选项:
该选项默认指定的事务管理器是bean id为transactionManager的对象,完整配置为:
接下来最重要的是要在操作数据的service层增加@Transactional注解(javax.transaction.Transactional),例如: