??xml version="1.0" encoding="utf-8" standalone="yes"?> 通过讄hibernate映射文g的class?dynamic-insert="true" dynamic-update="true" 和property 里面的insert="false" update="false" 实现 . 两处都要配置Q?/p> <property></property>标签属性:update=”true|false” 如果讄为false,则在hibernate的update语句里面没有<property>标签所指明的属性所对应的字Dc?/p> 同理Qinsert=”true|false” 如果讄为false,则在hibernate的insert语句里面没有<property>标签所指明的属性所对应的字Dc?/p> q样的弊端是无法从表单上填写信息了?/p> 转自Q?/span>http://www.cnblogs.com/abllyboy/archive/2010/12/23/1914577.html 建立好数据库后,点击一个键Q代码就生成了,q实在是份十分惬意的事情Q前面有介绍Hibernate Tools可以生成代码,那么我们怎么利用它来生成代码呢?/p> 下面把详细步骤贴出来,同样Q有图有真相?/p> Step1Q安装好Hibernate ToolsQ徏立一个Dynamic web project,W者工E名?#8220;HibernateTest” Step2Q笔CMysql为示例,所以安装一个MysqlQ徏立相应测试数据库及表Q下图ؓW者的数据库及?/p> Step3Q将MySql的Jdbc驱动拯至lib目录Q笔者的为mysql-connector-java-5.1.14-bin.jarQ可以去Mysql官网下蝲 Step4Q利用Hibernate Tools生成hibernate.cfg.xml文gQ如下图Q?/p> 点击后可以对hibernate.cfg.xml命oQ不它直接默认转到下一步的配置界面Q笔者的配置如下图: 点击完成后,它将生成如下xml的配|文?/p> Step5QHibernate Console 配置 a.右键工程Q点击Run as-Run Configurationsq入如下界面q择Hibernate Console ConfigurationQ?/p> b.新徏一个Configure名ؓHibernateConsoleQ名字可随个人爱好来命名 W者各标签配|如下: Step6:利用Hibernat Tools生成reveng.xml a.工程中右键如下图Q添加reveng.xml b.没啥说的命个名,选择攄位置 c.按照头方向q行操作Q选择console的配|,再点d斎ͼp看到数据库中的表Q将它们Includeq来Q如下图 d:最l效?/p> Step7:q是最后一步了Q激动h心的时刻pC a.在Eclipse的工h中将Hibernate Code Generate昄出来Q显C出来后点击Hibernate Code Generate ConfigurationsQ如下图: b.Main标签中选择控制収ͼ选择文g输出路径Q包名,reveng.xml文g c.Exporters标签,选择要生成的文gQ记得勾上Hebernate xml Mappings及Hebernate xml Configuration,它们自动生成映文件ƈ注册Q?/p> 配置好后Q点击Run卛_生成代码?/p> 大功告成Q最后的生成的代码结构如下图Q?/p> 感谢你的阅读Q希望本文对你有用!
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
]]>
JavacM字段的类型ؓ java.util.Date
<property name="createdDate" type="timestamp" >
<column name="CREATED_DATE" />
</property>
映射文g中property元素的type属性gؓ timestamp .
]]>
<class name="org.gecs.hibernate.test.AdDepartment" table="AD_DEPARTMENT" schema="BARCODE"
dynamic-insert="true" dynamic-update="true">
<id name="adDepartmentId" type="long">
<column name="AD_DEPARTMENT_ID" precision="22" scale="0" />
<generator class="sequence">
<param name="sequence">AD_DEPARTMENT_SEQ</param>
</generator>
</id>
<property name="departmentName" type="string">
<column name="DEPARTMENT_NAME" length="50" not-null="true" />
</property>
<property name="active" type="java.lang.Character" insert="false" update="true">
<column name="ACTIVE" length="1" />
</property>
<property name="createdTime" type="date" insert="false" update="false">
<column name="CREATED_TIME" length="7" />
</property>
<property name="createdUser" type="string">
<column name="CREATED_USER" length="20" not-null="true" />
</property>
<many-to-one name="parentDepartment" column="PARENT_DEPARTMENT_ID"/>
<set name="childDepartment" cascade="save-update" lazy="true" inverse="true">
<key column="PARENT_DEPARTMENT_ID"/>
<one-to-many class="org.gecs.hibernate.test.AdDepartment"/>
</set>
</class>
</hibernate-mapping>
表结构:
AdDepartment department = new AdDepartment();
department.setDepartmentName("華南資訊?);
department.setCreatedUser("bob");
AdDepartment child_department = new AdDepartment();
child_department.setDepartmentName("PCBA應用pȝ?);
child_department.setCreatedUser("bob");
child_department.setParentDepartment(department);
//
department.getChildDepartment().add(child_department);
Transaction tran = session.beginTransaction();
session.save(department);
//session.save(child_department);
tran.commit();
}
效果Q?/span>
]]>
<class name="org.gecs.hibernate.test.AdDepartment" table="AD_DEPARTMENT" schema="BARCODE"
dynamic-insert="true" dynamic-update="true">
<id name="adDepartmentId" type="long">
<column name="AD_DEPARTMENT_ID" precision="22" scale="0" />
<generator class="sequence">
<param name="sequence">AD_DEPARTMENT_SEQ</param>
</generator>
</id>
<property name="departmentName" type="string">
<column name="DEPARTMENT_NAME" length="50" not-null="true" />
</property>
<property name="active" type="java.lang.Character" insert="false" update="true">
<column name="ACTIVE" length="1" />
</property>
<property name="createdTime" type="date" insert="false" update="false">
<column name="CREATED_TIME" length="7" />
</property>
<property name="createdUser" type="string">
<column name="CREATED_USER" length="20" not-null="true" />
</property>
</class>
</hibernate-mapping>
]]>
]]>
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
at javax.naming.InitialContext.unbind(InitialContext.java:416)
at org.hibernate.impl.SessionFactoryObjectFactory.removeInstance(SessionFactoryObjectFactory.java:116)
at org.hibernate.impl.SessionFactoryImpl.close(SessionFactoryImpl.java:806)
at org.hibernate.test.junit.UserTest.tearDown(UserTest.java:43)
at junit.framework.TestCase.runBare(TestCase.java:130)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
<session-factory name="foo">
<property name="hibernate.connection.url">jdbc:oracle:thin:@10.240.144.25:1521:MES</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.username">*****</property>
<property name="hibernate.connection.password">*****</property>
<property name="dialect">org.hibernate.dialect.OracleDialect</property>
<property name="show_sql">true</property>
<mapping resource="org/hibernate/test/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
原因Q?lt;seesion-factory>元素多了属?name.
]]>
http://sourceforge.net/projects/hibernate/files/
先决条gQ?/font>
已经安装?/span>ant?/span>MySQL数据库,数据库表已经建立?/span>
1?span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> ?/span>Hibernate官方|站下蝲Middlegen-Hibernate?/span>hibernate-extensionsQƈ解压?/span>
2?span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> 配置Middlegen-Hibernate:
2.1 配置数据库连?/span>
假设q接的数据库?/span>MySQLQ在Middlegen-Hibernate-r5\config\database目录中有一?/span>mysql.xml文gQ是用来配置MySQL数据库的q接的。内容ؓQ?/span>
<property name="database.script.file" value="${src.dir}/sql/${name}-mysql.sql"/>
<property name="database.driver.file" value="${lib.dir}/mysql-connector-java-3.0.15-ga-bin.jar"/>
<property name="database.driver.classpath" value="${database.driver.file}"/>
<property name="database.driver" value="org.gjt.mm.mysql.Driver"/>
<property name="database.url" value="jdbc:mysql://localhost/jboss"/>
<property name="database.userid" value="jboss"/>
<property name="database.password" value="jboss"/>
<property name="database.schema" value=""/>
<property name="database.catalog" value=""/>
<property name="jboss.datasource.mapping" value="mySQL"/>
?/span>mysql-connector-java-3.0.15-ga-bin.jar拯?/span>${lib.dir}Q也是Middlegen-Hibernate-r5\lib目录?/span>
修改配置文g中的数据库连接项?/span>database.url?/span>database.userid?/span>database.userid ?/span>Middlegen-Hibernate可以扑ֈ数据库?/span>
2.2 配置Middlegen-Hibernate-r5?/span>antq行文gbuild.xml
<!DOCTYPE project [
<!ENTITY database SYSTEM "file:./config/database/mysql.xml">
]>
指出使用的数据库配置文g?/font>
<project name="Middlegen Hibernate" default="all" basedir=".">
<property file="${basedir}/build.properties"/>
<property name="name" value="hibernatesample"/>
指出你的应用名称?/font>
<property name="build.gen-src.dir" value="C:/sample"/>
指出hbm的输\径?/span>
<hibernate
destination="${build.gen-src.dir}"
package="org.hibernate.sample"
genXDocletTags="false"
genIntergratedCompositeKeys="false"
javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"
/>
指出hbm所在的包的位置?/span>
指出hbm.xml中是否需?/span>XDoclet Tags?/span>
3?span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> q行Middlegen-Hibernate:
?/span>Middlegen-Hibernate目录下运?/span>antQ进?/span>Middlegen-Hibernate的图形界面。可以设|表Q和字段的特性。然后按GenarateQ?/span>hbm.xml文g?/span>
4?span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> 配置hibernate-extensions
?/span>hibernate-extensions-2.1.2\tools\bin目录有一?/span>setenv.bat文gQ改变其内容为:
set JDBC_DRIVER=C:\java\Middlegen-Hibernate-r5\lib\mysql-connector-java-3.0.15-ga-bin.jar
set HIBERNATE_HOME=C:\java\hibernate-2.1.6
set CORELIB=%HIBERNATE_HOME%\lib
set LIB=..\lib
set PROPS=%HIBERNATE_HOME%\src
set CP=%JDBC_DRIVER%;%PROPS%;%HIBERNATE_HOME%\hibernate2.jar;%CORELIB%\commons-logging-1.0.4.jar;%CORELIB%\commons-collections-2.1.1.jar;%CORELIB%\commons-lang-1.0.1.jar;%CORELIB%\cglib-full-2.0.2.jar;%CORELIB%\dom4j-1.4.jar;%CORELIB%\odmg-3.0.jar;%CORELIB%\xml-apis.jar;%CORELIB%\xerces-2.4.0.jar;%CORELIB%\xalan-2.4.0.jar;%LIB%\jdom.jar;%LIB%\..\hibernate-tools.jar
注意U色字体提示的均是\径和JAR文g名,一定要正确?/span>
5、运?/span>hibernate-extensionsQ根?/span>hbm.xml产生POJO文g
?/span>DOS中运?/span>hbm2java c:\sample\org\hibernate\sample\*.xml --output=c:\sample\Student.hbm.xml
...
<hibernate-mapping>
<class name="model.Student" table="student">
<id name="id" unsaved-value="null">
<generator class="uuid.hex"/>
</id>
<property name="name" type="string"/>
<set name="courses"
table="student_course"
cascade="save-update"
>
<key column="stu_id"/>
<many-to-many class="model.Course
column="course_id"/>
</set>
<class>
</hibernate-mapping>
多对多关p需要配|的属性比较多一些。初学者经怼?lt;key column=""/>?lt;column="">的?br />
弄反了,其实只要C一个原则:<key column="">L和本w类的主键id对应Q?lt;column="">
L与关联类的主键id相对应。对于上面的Student.hbm.xml,兌cLCourse,本ncd是Student
Course.hbm.xml
...
<hibernate-mapping>
<class name="model.Course" table="course">
<id name="id" unsaved-value="null">
<generator class="uuid.hex"/>
</id>
<propery name="name" type="string"/>
<set name="students"
table="student_course"
cascade="save-update"
>
<key columm="course_id"/>
<many-to-many class="model.Student"
column="stu_id"/>
</set>
</class>
</hibernate-mapping>
注意QStudent与Course的cascade都设|ؓsave-updateQ在多对多的关系中,all,delete{?br />
cascade是没有意义的Q因为多对多关系中,q不能因为父对象被删除,而造成被包括的子对?br />
被删除,因ؓ可能q有其他的父对象参考了q个子对象?/span>
另外Q在多对多关pMQ如果双斚w有控制权Q也是双方都没有设|inverse="true"Q,?br /> 双方都要把关联关pd映到数据库。必d某一方设|inverse="true"Q然后在执行语句时?br /> L方进行操作(也就是没有设|inverse="true"的那一方)?/strong>
单向兌
双向兌
本节中用到两个c,分别是班U?Team)和学?Student)Q学生和班之间是多对一
关系?br />
具体的关联实现源代码如下Q?br />
Student.hbm.xml
...
<hibernate-mapping>
<class name="model.Student" table="student">
<id name="id" unsaved-value="null">
<generator class="uuid.hex"/>
</id>
<property name="name" type="string'/>
<many-to-one name="team"
class="model.Team"
column="team_id" <!--和team发生兌的列?->
cascade="none"
fetch="join"
/>
</class>
</hibernate-mapping>
<many-to-one>标签hcolumn属性,column属性L和关联类Q对于Student来说Q关联类
是TeamQ的主键id 相对应,因此Hibernate会根据student表中的team_idQ根据Team表中讄
的id列(一般情况列名也叫idQ,取出team.id=student.team_id的记录,构造成Team对象q?br />
回给StudentcR?/strong>
Team.hbm.xml
...
<hibernate-mapping>
<class name="model.Team" table="team" lazy="true">
<id name="id" unsaved-value="null">
<generator class="uuid.hex"/>
</id>
<property name="teamName" type="string"/>
<set name="students" cascade="save-update" lazy="true" inverse="true">
<key column="team_id"/>
<one-to-many class="model.Student"/>
</set>
</class>
</hibernate-mapping>
Team对Student是一对多关系Q一对多h<key column=""/>属性,key标签L和本w类的主?br />
相对应。在取得Team对象Ӟ通过Team的主键id与Student表中的team_idq行匚wQ如?br />
team.id=student.team_idQ则认ؓ此学生是本班U的Q于是加载学生,把学生对象加入Team
对象的学生集合?/strong>
讄inverse标签
׃在Team.hbm.xml中设|了inverse="true",Team和Student之间的关p{由Student来维?br />
因此Q当Team掌握l护权时(inverse="false"或者默认状态)Q它负责自qid告诉Student
Q然后Hibernate发送update语句L新记录。但现在讄了inverse="true"之后Q维护权?br />
Student手中Q于是Hibernate不再发送update语句Q而由Student自动d得team_idQ而这?br />
动作其实是完成一?#8220;学生d班”动作Q也是语句newStu.setTeam(team)?/p>
以主键关?br />
主键关系的重ҎQ关联的两个实体׃n一个主键倹{?br />
Student.hbm.xml
...
<hibernate-mapping>
<class name="model.Student" table="student" lazy="true"><!--把类和表兌h-->
<id name="id" unsaved-value="null"><!--id的生方式是uuid.hex-->
<generator class="uuid.hex"/>
</id>
<property name="name" type="sring"/>
<one-to-one name="cer"
class="model.Certificate"
fetch="join"
cascade="all"
/><!--映射对应的n份证对象-->
</class>
</hibernate-mapping>
Certificate.hbm.xml
...
<hibernate-mapping>
<class name="model.Certificate" table="certificate" lazy="true">
<id name="id">
<!--外键生成机制Q引用stu对象的主键作为certificate数据表的主键和外?->
<generator class="foreign">
<param name="property">stu</param>
</generator>
</id>
<one-to-one name="stu"
class="model.Student"
constrained="true" <!--表示Certificate引用了stu的主键作为外?->
/>
</class>
</hibernate-mapping>
上述的两个配|文件在<one-to-one>标签中都没有讄column属?br /> Q实际上<one-to-one>标签本n没有column属性)?br />
以外键关?/em>
以外键关联的重点是:两个实体各自有不同的主键Q但其中一个实体有一个外键引?br />
了另一个表的主键?/p>
Student.hbm.xml
...
<hibernate-mapping>
<class name="model.Student" table="student" lazy="true">
<id name="id" nusaved-value="null">
<generator class="uuid.hex"/>
</id>
<property name="name" type="sring"/>
<one-to-one name="cer"
class="model.Certificate"
fetch="join"
cascade="all"
/><!--映射对应的n份证对象-->
</class>
</hibernate-mapping>
可以看到Student.hbm.xml和以主键兌时的代码是一LQƈ没有改变?/p>
Certificate.hbm.xml
...
<hibernate-mapping>
<class name="model.Certificate" table="certificate" lazy="true">
<id name="id">
<generator class="uuid.hex"/> <!--不再是foreign?->
</id>
<many-to-one name="stu"
class="model.Student"
unique="true" <!--唯一的多对一Q其实也变成了一对一关系-->
column="stu_id"
/>
</class>
</hibernate-mapping>
以外键关联的一对一Q其实本质上变成了一对多的双向关联了Q编写时直接
按照一对多和多对一的要求编写,最后在many-to-oneq一边上加上一?br />
unique="true"卛_?/p>
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class); detachedCriteria.add(Restrictions.eq("name", "department")).createAlias("employees", "e").add(Restrictions.gt(("e.age"), new Integer(20))); |
detachedCriteria.getExecutableCriteria(session).list(); |
HibernateTemplate.execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { .... } } |
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class); detachedCriteria.createAlias("employees", "e").add(Restrictions.eq("name", "department")).add(Restrictions.gt(("e.age"), new Integer(20))); departmentManager.findByCriteria(detachedCriteria); |
public List findByCriteria(final DetachedCriteria detachedCriteria) { return (List) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = detachedCriteria.getExecutableCriteria(session); return criteria.list(); } }); } |
Criteria criteria = detachedCriteria.getExecutableCriteria(session); return criteria.list(); |
private boolean exposeNativeSession = false; ... |
Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session)); |
public Criteria getExecutableCriteria(Session session) { impl.setSession( (SessionImpl) session ); // 要求SessionImplQSpring传递的是Proxy return impl; } |
public List findByCriteria(final DetachedCriteria detachedCriteria) { return (List) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = detachedCriteria.getExecutableCriteria(session); return criteria.list(); } }, true); } |
一对多、多对多Q末端ؓ多)的情况:在集合的配置中设|,?set ZQ如下所C:
<set name="students" inverse="true" cascade="all" lazy="false" batch-size="2" ><!-- 一对多的gq加载设|?-->
<key>
<column name="TEAMID" length="32" not-null="true" />
</key>
<one-to-many class="edu.dgut.ke.model.Student" />
</set>
一对一、多对一Q末端ؓ一Q的情况Q如果要Ҏ端ؓ一的关联设|批量加载,要在“一”q端的配|文件中q行讄Q比如学生对w䆾证,要实现对班的批量加载,应设|如?br />
<class name="edu.dgut.ke.model.Certificate" table="CERTIFICATE" lazy="true" batch-size="10" >
试例子
1.不管Acdproperty1在配|文仉是什么策?可能是预先抓?立即或gq检?它们都失?,q时都采用HQL指定的左外连?左外q接必定会初始化property1属?或对?,但是如果配置文g里对property1的检索策略是延迟加蝲,Acd 到对properyt1的引?Z得到q个引用,需要再ơ发送一条SQL语句来确立这U引用关p?q种情况在property1为集合时l常出现.
2.Acd配置文g中设|的对property2的预先抓取策略将被忽?/strong>(不管q个{略是fetch或是select),对property2有媄响的讄是立卛_延迟加蝲,hibernate只看得到q两U策?所以在使用语句"from A as a left outer join a.property1"?property2的加载策略将仅由lazy="true"或者是lazy="false"来决?nbsp;
Team.hbm.xml
... ...
<set name="students" inverse="true" cascade="all" lazy="true" fetch="join"><!-- 一对多的gq加载设|?-->
<key>
<column name="TEAMID" length="32" not-null="true" />
</key>
<one-to-many class="edu.dgut.ke.model.Student" />
</set>
... ...
Student.hbm.xml
... ...
<many-to-one name="certificate"
class="edu.dgut.ke.model.Certificate"
unique="true"
column="cardId"
cascade="all"
lazy="false"
fetch="join">
</many-to-one>
<many-to-one name="team" class="edu.dgut.ke.model.Team" fetch="join">
<column name="TEAMID" length="32" not-null="true" />
</many-to-one>
... ...
试代码
Session session = HibernateSessionFactory.getSession();
List list = session.createQuery("from Student as s left join s.team").list();
HibernateSessionFactory.closeSession();
//list 包括两个长度?的数l?每一个数l中包括一个学生对象和一个班U对?br />
Object[] stuAndTeam1 = (Object[]) list.get(0);
Student stu = (Student) stuAndTeam1[0];
System.out.println(stu.getStudentname());
System.out.println(stu.getTeam().getTeamname());
System.out.println(stu.getTeam().getStudents().size());
取? full.classname.of.Dialect
取? SCHEMA_NAME
取? jndi/composite/name
取? true | false
取? 讄?tt class="literal">0?tt class="literal">3之间
取? 值在 5 ?30之间?
取? true | false
取? true | false
取? true | false
取? 1, 2, 4, 8
取? classname.of.ConnectionProvider
取? classname.of.CacheProvider
取? classname.of.TransactionFactory
取? jndi/composite/name
取? classname.of.TransactionManagerLookup
取? hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC
取? true | false
取? update | create | create-drop
public class Query {
public static void main(String[] args) {
//打开Session取得Student对象,后关闭Session
Student student = getStudent();
//打开另一个Session.调用update()Ҏ,因ؓ在上面的Session关闭?
//student对象成了q状?在另一个Session中无法初始化一个脱对?必须重新兌
HibernateSessionFactory.getSession().update(student.getTeam());
//使用initializeҎ初始化一个代理对象或者集?此代理ƈ不能保证内部嵌套的对象或者集合被初始?
Hibernate.initialize(student.getTeam());
System.out.println(student.getTeam().getTeamname());
HibernateSessionFactory.closeSession();
}
...
public static Student getStudent() {
StudentDAO studentDAO = new StudentDAO();
Session session = studentDAO.getSession();
Student student = (Student) session.get(Student.class, "2c9ab2d516056609011605660e7e0001");
session.close();
return student;
}
...
}
很多E序需要在某个事务中获取对象,然后对象发送到界面层去操作Q最后在一个新的事务保存所做的修改?在高q发讉K的环境中使用q种方式Q通常使用附带版本信息的数据来保证q些“?#8220;工作单元之间的隔R?
Hibernate通过提供使用Session.update()?tt class="literal" style="color: #0000ff">Session.merge()Ҏ 重新兌q实例的办法来支持q种模型?
// in the first session Cat cat = (Cat) firstSession.load(Cat.class, catId); Cat potentialMate = new Cat(); firstSession.save(potentialMate); // in a higher layer of the application cat.setMate(potentialMate); // later, in a new session secondSession.update(cat); // update cat secondSession.update(mate); // update mate
如果hcatId持久化标识的Cat之前已经?tt class="literal">另一Session(secondSession)装蝲了, 应用E序q行重关联操?reattach)的时候会抛出一个异常?
如果你确定当前session没有包含与之h相同持久化标识的持久实例Q?tt class="literal">update()?如果想随时合q你的的改动而不考虑session的状态,使用merge()?/strong> 换句话说Q在一个新session中通常W一个调用的?tt class="literal">update()ҎQ以便保证重新关联脱?detached)对象的操作首先被执行?
希望相关联的q对象Q通过引用“可到?#8221;的脱对象)的数据也要更新到数据库时Qƈ且也仅仅在这U情况)Q?应用E序需要对该相兌的脱对象单独调?tt class="literal">update() 当然q些可以自动完成Q即通过使用传播性持久化(transitive persistence)Q请?a title="11.11. 传播性持久化(transitive persistence)" tppabs="http://www.hibernate.org/hib_docs/v3/reference/zh-cn/html/objectstate.html#objectstate-transitive">W?nbsp;11.11 ?“传播性持久化(transitive persistence)”?
lock()Ҏ也允许程序重新关联某个对象到一个新session上。不q,该脱?detached)的对象必L没有修改q的Q?
//just reassociate: sess.lock(fritz, LockMode.NONE); //do a version check, then reassociate: sess.lock(izi, LockMode.READ); //do a version check, using SELECT ... FOR UPDATE, then reassociate: sess.lock(pk, LockMode.UPGRADE);
h意,lock()可以搭配多种LockModeQ?更多信息请阅读API文以及关于事务处理(transaction handling)的章节。重新关联不?tt class="literal">lock()的唯一用途?
其他用于长时间工作单元的模型会在W?nbsp;12.3 ?“乐观q发控制(Optimistic concurrency control)”中讨论?
文章出处:http://docs.huihoo.com/framework/hibernate/reference-v3_zh-cn/objectstate.html分页支持c:
抽象业务c?
用户在web层构造查询条件detachedCriteriaQ和可选的startIndexQ调用业务bean的相应findByCriteriaҎQ返回一个PaginationSupport的实例ps?/p>
ps.getItems()得到已分好的结果集
ps.getIndexes()得到分页索引的数l?
ps.getTotalCount()得到ȝ果数
ps.getStartIndex()当前分页索引
ps.getNextIndex()下一늃?
ps.getPreviousIndex()上一늃?br />
文章出处:http://www.javaeye.com/topic/14657
q void delete(Object entity)Q删除指定持久化实例
q deleteAll(Collection entities)Q删除集合内全部持久化类实例
q find(String queryString)Q根?/span>HQL查询字符串来q回实例集合
q findByNamedQuery(String queryName)Q根据命名查询返回实例集?/span>
q get(Class entityClass, Serializable id)Q根据主键加载特定持久化cȝ实例
q save(Object entity)Q保存新的实?/span>
q saveOrUpdate(Object entity)Q根据实例状态,选择保存或者更?/span>
q update(Object entity)Q更新实例的状态,要求entity是持久状?/span>
q setMaxResults(int maxResults)Q设|分늚大小
下面是一个完?/span>DAOcȝ源代码:
public class PersonDAOHibernate implements PersonDAO
{
//采用log4j来完成调试时的日志功?/span>
private static Log log = LogFactory.getLog(NewsDAOHibernate.class);
//以私有的成员变量来保?/span>SessionFactory?/span>
private SessionFactory sessionFactory;
//以私有变量的方式保存HibernateTemplate
private HibernateTemplate hibernateTemplate = null;
//讑ր注?/span>SessionFactory必需?/span>setterҎ
public void setSessionFactory(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
//初始化本DAO所需?/span>HibernateTemplate
public HIbernateTemplate getHibernateTemplate()
{
//首先Q检查原来的hibernateTemplate实例是否q存?/span>
if ( hibernateTemplate == null)
{
//如果不存在,新徏一?/span>HibernateTemplate实例
hibernateTemplate = new HibernateTemplate(sessionFactory);
}
return hibernateTemplate;
}
//q回全部的h的实?/span>
public List getPersons()
{
//通过HibernateTemplate?/span>findҎq回Person的全部实?/span>
return getHibernateTemplate().find("from Person");
}
/**
* Ҏ主键q回特定实例
* @ return 特定主键对应?/span>Person实例
* @ param 主键?/span>
public News getNews(int personid)
{
return (Person)getHibernateTemplate().get(Person.class, new Integer(personid));
}
/**
* @ person 需要保存的Person实例
*/
public void savePerson(Person person)
{
getHibernateTemplate().saveOrUpdate(person);
}
/**
* @ param personid 需要删?/span>Person实例的主?/span>
* /
public void removePerson(int personid)
{
//先加载特定实?/span>
Object p = getHibernateTemplate().load(Person.class, new Integer(personid));
//删除特定实例
getHibernateTemplate().delete(p);
}
}
q Object execute(HibernateCallback action)
q List execute(HibernateCallback action)
q两个方法都需要一?/span>HibernateCallback的实例,HibernateCallback实例可在M有效?/span>Hibernate数据讉K中用。程序开发者通过HibernateCallbackQ可以完全?/span>Hibernate灉|的方式来讉K数据库,解决Spring装Hibernate后灵zL不的~陷?/span>HibernateCallback是一个接口,该接口只有一个方?/span>doInHibernate(org.hibernate.Session session)Q该Ҏ只有一个参?/span>Session?/span>
通常Q程序中采用实现HibernateCallback的匿名内部类来获?/span>HibernateCallback的实例,ҎdoInHibernate的方法体是Spring执行的持久化操作。具体代码如下:
public class PersonDaoImpl implements PersonDao
{
//U有实例变量保存SessionFactory
private SessionFactory sessionFactory;
//依赖注入必须?/span>setterҎ
public void setSessionFactory(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
/**
* 通过人名查找所有匹配该名的Person实例
* @param name 匚w的h?/span>
* @return 匚w该Q命的全部Person集合
*/
public List findPersonsByName(final String name)
{
//创徏HibernateTemplate实例
HibernateTemplate hibernateTemplate =
new HibernateTemplate(this.sessionFactory);
//q回HibernateTemplate?/span>execute的结?/span>
return (List) hibernateTemplate.execute(
//创徏匿名内部c?/span>
new HibernateCallback()
{
public Object doInHibernate(Session session) throws HibernateException
{
//使用条g查询的方法返?/span>
List result = session.createCriteria(Person.class)
.add(Restrictions.like(“name”, name+”%”)
.list();
return result;
}
});
}
}
注意Q方?/span>doInHibernateҎ内可以访?/span>SessionQ该Session对象是绑定到该线E的Session实例。该Ҏ内的持久层操作,与不使用Spring时的持久层操作完全相同。这保证对于复杂的持久层讉KQ依然可以?/span>Hibernate的访问方式?/span>
一?span style="font: 7pt 'Times New Roman'"> 数据库事务概?/span>
数据库事务的特征Q?/span> ACID
Atomic Q原子性)?/span> Consistency Q一致性)?/span> Isolation Q隔L)?/span> Durability Q持久性)?/span> DBMS 用日志来保证数据的原子性、一致性和持久性;用锁的机制来保证数据的隔L?/span>
二?span style="font: 7pt 'Times New Roman'"> 事务的边?/span>
数据库支?/span> 2 U事务模式:自动提交和手动提交?/span>
JDBC API 的事务边?/span>
Hibernate API 声明事务边界
注:一?/span> session 可以对应多个事务Q但是推荐的做法是一?/span> session 对应一个事务?/span>
三?/font>
多事务的q发问题当多个事务同时访问相同的数据的时候,E序如果没有采取适当的隔L施,׃发生数据库的q发问题。常见的q发问题有:
W一cM失更斎ͼ撤消事务的时候,把其他的事务已经提交的数据给覆盖了;
脏读Q读了没有提交的数据Q?/span>
虚读Q一个事务读到另外一个事务已l提交的新插入的数据Q?/span>
不可重复读:一个事务读到另外一个事务已l提交的更新的数据;
W二cM失更斎ͼ一个事务覆盖另外一个事务已l提交的更新数据?/span>
四?/strong> ?/span>
一般地Q大型的 DBMS 都会自动的管理锁定机Ӟ但是在对数据的安全性、完整性和一致性有Ҏ要求的地方,可以׃务本w来理琐的机制?/span>
有一点要x的是Q锁的粒度越大,隔离性越好,q发性越差?/span>
按照锁的E度来分有:
׃n锁:用读操作Q非独占的,其他事务可以读,但是不能更新Qƈ发性好Q?/span>
独占锁:用与 insert update ?/span> delete {语句,其他事务不能读,也不能改Qƈ发性差Q?/span>
更新锁:执行 update 的时候,加锁?/span>
ȝQ多是事务分别锁定了一个资源,又请求锁定对方已l锁定的资源Q就造成了请求环?/span>
降低死锁的最好办法是使用短事务?/span>
五?/font> 数据库的事务隔离U别
数据库提?/span> 4 U事务隔ȝ别:
Serializable Q串行化Q(隔离U别最高) 1
Repeatable Read Q可重复读; 2
Read Commited Q读已提交数据; 4
Read Uncommited Q读未提交数据;Q隔ȝ别最低) 8
Hiberate 中的隔离U别的设|?/span>
?/span> Hibernate 的配|文件中 hibernate.connection.isolation=2
六?/font> 悲观锁和乐观?/span>
从应用程序的角度来看Q锁分ؓ悲观锁和乐观锁?/span>
悲观锁:昄的ؓE序加锁Q但是降低ƈ发性?/span>
Select ……. For update;
?/span> Hibernate 中的代码
Session.get(Account.class,net Long(1),LockMode.UPGRADE) Q?/span> // E序采用悲观?/span>
乐观锁:依靠 DBMS 来管理锁Q程序依靠版本控制来避免q发问题?/span>
在对?/span> - 关系映射的文件中Q用 <version> 或?/span> <timestamp> 可以理q发。乐观琐比悲观琐有更好的q发性,优先考虑乐观琐?/span>
Hibernate 提供?/span> 3 U检索策略:
l 延迟索;
l 立即索;
l q切左外q接Q?/span>
Hibernate 提供 2 U方式来定索策略,一中是在配|文件当中,另外一U是在程序种讄。当Ӟ如果你在E序中设|了索策略,那么你在配置文g中的讄也就无效了。另外的一U情冉| HQL 会忽略配|文件的讄Q而L采用q切左外q接?/span>
一?cȝ别的?/span>
可以选择的检索策略是立即索和延迟索,默认的是立即索。用配置文g中的 <class> 节点?/span> lazy 来控制?/span>
注意Q不你在配|?/span> class ?/span> lazy ?/span> true q是 false Q对 get() ?/span> create Criteria () Ҏ都不起作用,只有?/span> load() Ҏ起作用?/span>
当你使用的检索策略是 lazy 的时候,当你执行
Customer customer = (Customer)session.load(Customer.class,new Long(1));
的时候, Hibernate 不从数据库检索数据,而只是生一个代理类Q只有当你执?/span>
Customer.getName();
的时候, Hibernate 才到数据库取数据。所以,如下的代码是会被抛出异常的:
get() ҎL用的立即索,如果和它相关联的cM是用的立x索,那么也会把相兌的数据也索出来?/span>
二?一对和多对多关联检?/span>
一般地Qؓ了有减少Ҏ据库的访问,我们往往用gq检索的{略。所以,我们优先使用如下方式Q?/span>
<set class=”order” inverse=”true’ lazy=”true” >
但是Q我们在?#8220;?#8221;的一方的时候, Hibernate 不能为我们生代理类。由此,我们p?/span> betch-size 的配|来减少 SQL 语句?/span>
当我们?/span> outer-join 属性的时候,我们没有必要?/span> lazy 属性了?/span> Outer-join 会一ơ将“一”方和与之相关?#8220;?#8221;方用左外q接的方式检索出来?/span>
Session session = sessionFactory.openSession();
Transaction tx = null;
tx = session.beginTransaction();
Customer customer = (Customer)session.get(Customer.class,new Long(1));
产生?/span> SQL 语句如下Q?/span>
Hibernate: select customer0_.ID as ID1_, customer0_.NAME as NAME2_1_, orders1_.CUSTOMER_ID as CUSTOMER3_3_, orders1_.ID as ID3_, orders1_.ID as ID0_, orders1_.ORDER_NUMBER as ORDER2_1_0_, orders1_.CUSTOMER_ID as CUSTOMER3_1_0_ from sampledb.customers customer0_ left outer join sampledb.orders orders1_ on customer0_.ID=orders1_.CUSTOMER_ID where customer0_.ID=?
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import cn.hxex.blog.hibernate.HibernateUtil;
public class HibernateFilter implements Filter {
private static Log log = LogFactory.getLog(HibernateFilter.class);
/**
* qo器的主要Ҏ
* 用于实现Hibernate事务的开始和提交
*/
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException
{
// 得到SessionFactory对象的实?br> SessionFactory sf = HibernateUtil.getSessionFactory();
try
{
// 开始一个新的事?br> log.debug("Starting a database transaction");
sf.getCurrentSession().beginTransaction();
log.debug( "Request Path:\t" + ((HttpServletRequest)request).getServletPath() );
// Call the next filter (continue request processing)
chain.doFilter(request, response);
// 提交事务
log.debug("Committing the database transaction");
sf.getCurrentSession().getTransaction().commit();
}
catch (Throwable ex)
{
ex.printStackTrace();
try
{
// 回滚事务
log.debug("Trying to rollback database transaction after exception");
sf.getCurrentSession().getTransaction().rollback();
}
catch (Throwable rbEx)
{
log.error("Could not rollback transaction after exception!", rbEx);
}
// 抛出异常
throw new ServletException(ex);
}
}
/**
* Servletqo器的初始化方?br> * 可以d配置文g中设|的配置参数
*/
public void init(FilterConfig filterConfig) throws ServletException {}
/**
* Servlet的销毁方?br> * 用于释放qo器所甌的资?br> */
public void destroy() {}
}
import java.io.Serializable;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
public class BaseModel implements Serializable{
/**
* The Generated SerialVersionUID
*/
private static final long serialVersionUID = 7766184319541530720L;
/**
* The identify of the object
*/
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/**
* Common implement equals method
*/
public boolean equals( Object obj )
{
if( this==obj ) return true;
if( !( obj instanceof BaseModel ) )
return false;
BaseModel target = (BaseModel)obj;
if( this.getId()!=null && this.getId().length()>0 )
{
return this.getId().equals( target.getId() );
}
if( target.getId()!=null && target.getId().length()>0 )
{
return false;
}
return EqualsBuilder.reflectionEquals(this, obj);
}
/**
* Generate the hash code
*/
public int hashCode()
{
if( this.getId()!=null && this.getId().length()>0 )
{
return this.getId().hashCode();
}
return HashCodeBuilder.reflectionHashCode(this);
}
/**
* Common implement toString method
*/
public String toString()
{
return ReflectionToStringBuilder.toString( this );
}
}
equals()Ҏ,用于判断两个对象是否相等,但ƈ不是在?=="q行两个对象是否相等的判断时调用.因ؓ使用"=="所判断的是两个对象的引用是否相{?也可以简单理解ؓ两个实例所引用的是否ؓ内存中的同一个对?equals()Ҏ可以理解Z个对象在"含义"上是否相{?也就是说q两个对象所表达的意思是否相?equals()Ҏ在对象保存到集合容器c?Collection)中时被调?因ؓ集合容器cM允许其中存在两个相同对象实例,其判断的依据是通过调用该实体对象的equals()Ҏ来进行判断的.
如果修改了equals()Ҏ,必M改hashCode()Ҏ.如果不这L?p反java.lang.Object的通用的hashCode的约?从而导致该cL法与Z散列值的集合cMh常工?
toString()Ҏ,用于当前Java对象的实例{换ؓ可以描述其内容的字符?q个Ҏ的作用是在程序调试的q程可以方便地得到实体对象中令h感兴的信息,有利于更准确及时地发现程序中的问?
对于Hibernate 3.1 以前的的版本在实现Hibernate工具cL,需要通过两个U程
局部变量来保存与当前进行相对应的Session和事务对象的实例.
而对于Hibernate 3.1 以后的版?使用U程局部变量保存Session和事务对象的
工作完全不需要自己去实现?只需在Hibernate.cfg.xml配置文g中增加一个名?br>Current_session_context_class的属?q且讄该属性的gؓthread.q样Hibernate
可以自动地使用U程局部变量来保存当前的进E的Session和事务对象了.
相应?Hibernate也ؓ其Session对象增加了getTransaction()Ҏ,以便可以随时
得到当前的事务ƈq行提交或者回滚操?q个Ҏ在以前版本的hibernate中是不存?br>?
Hibernate工具cM要包括以下功?
(1)Hibernate的初始化操作
q个功能不放在Q何方法中,采用静态编码的处理方式,在对象的初始化的时候被
调用一ơ就可以?
(2)得到当前的配|信?/em>
q个Ҏ可以得到当前的配|信?以便于动态进行配|参数的修改.hibernate
的配|信息只在Hibernate初始化的时候用一?在完成初始化之后寚w|文?br> 或者Configuration对象所做的修改不会生?
(3)得到SessionFactory对象的实?/em>
q个Ҏ用于得到当前pȝq行时的SessionFactory对象的实?q个对象的实?br> 对于整个pȝ而言是全局唯一?
(4)释放各种资源
q个Ҏ用于l止Hibernate的报务后,释放各种Hibernate所使用的资?虽然q个
Ҏ几乎不会用到,但对于申误源的及时释放是每个程序应该掌握的基本原则.
(5)重徏SessionFactory
׃SessionFactory对于整个Hibernate应用是唯一?q且是在Hibernate初始?br> 之后建立好的,而且对于配置文g的修改也不会影响到已l初始化的SessionFactory
对象.那么如何才能使修改的配置信息对Hibernate起作用呢.q就需要重建SessionFactory
对象实例.
(6)拦截器注?/em>
用于注册拦截器ƈ重徏SessionFactory.
HibenateUtil.java
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Interceptor;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
/**
* 基础的Hibernate辅助c,用于Hibernate的配|和启动?br> * <p>
* 通过静态的初始化代码来dHibernate启动参数Qƈ初始?br> * <tt>Configuration</tt>?lt;tt>SessionFactory</tt>对象?br> * <p>
*
* @author galaxy
*/
public class HibernateUtil
{
private static Log log = LogFactory.getLog(HibernateUtil.class);
// 指定定义拦截器属性名
private static final String INTERCEPTOR_CLASS = "hibernate.util.interceptor_class";
// 静态Configuration和SessionFactory对象的实例(全局唯一的)
private static Configuration configuration;
private static SessionFactory sessionFactory;
static
{
// 从缺省的配置文g创徏SessionFactory
try
{
// 创徏默认的Configuration对象的实?br> // 如果你不使用JDK 5.0或者注释请使用new Configuration()
// 来创建Configuration()对象的实?br> configuration = new Configuration();
// dhibernate.properties或者hibernate.cfg.xml文g
configuration.configure();
// 如果在配|文件中配置了拦截器Q那么将其设|到configuration对象?br> String interceptorName = configuration.getProperty(INTERCEPTOR_CLASS);
if (interceptorName != null)
{
Class interceptorClass =
HibernateUtil.class.getClassLoader().loadClass(interceptorName);
Interceptor interceptor = (Interceptor)interceptorClass.newInstance();
configuration.setInterceptor(interceptor);
}
if (configuration.getProperty(Environment.SESSION_FACTORY_NAME) != null)
{
// 让HibernateSessionFacoryl定到JNDI
configuration.buildSessionFactory();
}
else
{
// 使用静态变量来保持SessioFactory对象的实?br> sessionFactory = configuration.buildSessionFactory();
}
}
catch (Throwable ex)
{
// 输出异常信息
log.error("Building SessionFactory failed.", ex);
ex.printStackTrace();
throw new ExceptionInInitializerError(ex);
}
}
/**
* q回原始的Configuration对象的实?br> *
* @return Configuration
*/
public static Configuration getConfiguration()
{
return configuration;
}
/**
* q回全局的SessionFactory对象的实?br> *
* @return SessionFactory
*/
public static SessionFactory getSessionFactory()
{
SessionFactory sf = null;
String sfName = configuration.getProperty(Environment.SESSION_FACTORY_NAME);
if ( sfName != null)
{
log.debug("Looking up SessionFactory in JNDI.");
try
{
sf = (SessionFactory) new InitialContext().lookup(sfName);
}
catch (NamingException ex)
{
throw new RuntimeException(ex);
}
}
else
{
sf = sessionFactory;
}
if (sf == null)
throw new IllegalStateException( "SessionFactory not available." );
return sf;
}
/**
* 关闭当前的SessionFactoryq且释放所有的资源
*/
public static void shutdown()
{
log.debug("Shutting down Hibernate.");
// Close caches and connection pools
getSessionFactory().close();
// Clear static variables
configuration = null;
sessionFactory = null;
}
/**
* 使用静态的Configuration对象来重新构建SessionFactory?br> */
public static void rebuildSessionFactory()
{
log.debug("Using current Configuration for rebuild.");
rebuildSessionFactory(configuration);
}
/**
* 使用指定的Configuration对象来重新构建SessionFactory对象?br> *
* @param cfg
*/
public static void rebuildSessionFactory(Configuration cfg)
{
log.debug("Rebuilding the SessionFactory from given Configuration.");
synchronized(sessionFactory)
{
if (sessionFactory != null && !sessionFactory.isClosed())
sessionFactory.close();
if (cfg.getProperty(Environment.SESSION_FACTORY_NAME) != null)
cfg.buildSessionFactory();
else
sessionFactory = cfg.buildSessionFactory();
configuration = cfg;
}
}
/**
* 在当前SessionFactory中注册一个拦截器
*/
public static SessionFactory registerInterceptorAndRebuild(Interceptor interceptor)
{
log.debug("Setting new global Hibernate interceptor and restarting.");
configuration.setInterceptor(interceptor);
rebuildSessionFactory();
return getSessionFactory();
}
/**
* 获得拦截器对?br> *
* @return Interceptor
*/
public static Interceptor getInterceptor()
{
return configuration.getInterceptor();
}
/**
* 提交当前事务Qƈ开始一个新的事?br> */
public static void commitAndBeginTransaction()
{
sessionFactory.getCurrentSession().getTransaction().commit();
sessionFactory.getCurrentSession().beginTransaction();
}
}