关于hibernate的一些事 (此博文为http://my.oschina.net/u/555061/blog/506216后续)
1.简单说一下SessionFactory、Session 源自: http://blog.csdn.net/javaloveiphone/article/details/8155340
1.1、Hibernate中SessionFactory对象的创建代价很高,它是线程安全的对象,被设计成可以为所有的应用程序线程所共享。通常,SessionFactory会在应用程序启动时创建,一旦创建了SessionFactory将不会轻易关闭,只有当应用关闭时,SessionFactory才会关闭。
1.2、而Session的对象是轻量级的,它是线程不安全的。对于单个业务进程单个工作单元而言,Session只被使用一次。创建Session时,并不会立即打开与数据库之间的连接,Session只在需要进行数据库操作时,才会获取JDBC连接。因此,打开和关闭Session,并不会对性能造成很大的影响。甚至即使无法确定一个请求是否需要数据访问,也可以打开Session对象,因为如果不进行数据库访问,Session不会获取JDBC连接。
使用Spring管理hibernate的事务,在每个dao操作中使用SessionFactory.getCurrentSession()方法,该方法可以得到当前事务绑定的session。同时当前的Session和关联的Hibernate事务被绑定到当前线程上,虽然session不是线程安全的,但是通过这样的方式,每一个session都处于单线程中,避免session线程安全问题
1.3、不通过Spring管理事务,开启事务的主动性:
在sessionFactory.openSession()中,Hibernate会初始化数据库连接,与此同时,将其 AutoCommit设为关闭状态,这就是说,从SessionFactory获得session,其自动提交属性就已经被关闭了,事务需要主动、显示的调用才能生效,下面的代码不会对事务性数据库产生任何效果。
session=sessionFactory.openSession();
session.save(user);
session.close();
如果要使得代码真正作用到数据库,必须显示的调用Transaction指令
session=sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
前面1、2点都是没什么问题,但是第3点事务的问题,我跟该博主意见不一致,首先Spring可以管理由Hibernate的SessionFactory产生的事务,所以通过Spring管理Hibernate的事务是可行的。其次,在开启事务配置的同时,框架已经在自动帮你管理事务,也就是刚刚连续两个操作,一个save一个sqlquery,由于sqlquery失败导致save同时失败回滚(或者说就没有commit的后续操作),而如果再使用session.beginTransaction()则会导致org.hibernate.TransactionException: nested transactions not supported错误,分析字面上的意思和根据本人查询结果综合来看,就是因为多次开启事务导致错误,反过来说事务不需要在session.beginTransaction()的情况下才开启,框架自动已经就在配置好以后就开启了。
2.关于org.hibernate.MappingException: Unknown entity:错误
本人在发生的时候是由于没有写packagesToScan,以为可以在Spring自动包扫描的时候注册hibernateEmployee这个包下面的类为bean,没想到不行,需要在这里写
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.zhxjz.model.hibernateEmployee</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="dialect">${hibernate.dialect}</prop>
<prop key="show_sql">${hibernate.show_sql}</prop>
<!-- <prop key="hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> -->
</props>
</property>
</bean>
有博客提到代替packagesToScan的有另一种配置,其实也只是换汤不换药,这种方式未测试成功但应该是能用的,因此用*****代替需要配置的地方,先记录下
<property name="mappingDirectoryLocations">
<list>
<value>classpath:****</value>
</list>
</property>
来源:oschina
链接:https://my.oschina.net/u/555061/blog/506245