Hibernate学习三----------session详解
© 版权声明:本文为博主原创文章,转载请注明出处
如何获取session对象
1. openSession
2. getCurrentSession
- 如果使用getCurrentSession需要在hibernate.cfg.xml中进行如下配置:
如果是本地事务(jdbc事务)
<property name="current_session_context_class">thread</property>
如果是全局事务(jta事务)
<property name="current_session_context_class">jta</property>
- 全局事务和本地事务
本地事务适合对一个数据库进行操作,全局事务适合对多个数据库进行操作;
当存在多个数据库是,也就存在多个session,这样本地事务就无法对多个session进行统一管理,因此可以使用全局事务。
3. openSession和getCurrentSession区别
- getCurrentSession在事务提交或者回滚之后会自动关闭session,而openSession需要你手动关闭session。如果使用openSession而没有手动关闭,多次之后会导致连接池溢出
- openSession每次创建新的session对象,getCurrentSession使用现有的session对象
实例
1.项目结构
2.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.hibernate</groupId> <artifactId>Hibernate-Session</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>Hibernate-Session Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <hiberante.version>5.1.6.Final</hiberante.version> </properties> <dependencies> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- hibernate --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hiberante.version}</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.42</version> </dependency> </dependencies> <build> <finalName>Hibernate-Session</finalName> </build> </project>
3.hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <!-- 配置SessionFactory --> <session-factory> <!-- 设置数据库连接属性 --> <property name="connection.username">root</property> <property name="connection.password">***</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url"> jdbc:mysql:///hibernate?useSSL=true&characterEncoding=UTF-8 </property> <!-- 设置常用属性 --> <property name="show_sql">true</property><!-- 输出SQL --> <property name="format_sql">true</property><!-- 格式化SQL --> <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property><!-- 方言 --> <property name="hbm2ddl.auto">create</property><!-- 检查数据库表结构是否一致,不一致更新,一致忽略 --> <property name="current_session_context_class">thread</property><!-- 本地事务(jdbc事务) --> <!-- 引入映射文件 --> <mapping resource="hbm/Student.hbm.xml"/> </session-factory> </hibernate-configuration>
4.Student.java
package org.hibernate.model; import java.util.Date; public class Student { private long sid; // 学号 private String sname; // 姓名 private String gender; // 性别 private Date birthday; // 出生日期 private String address;// 地址 public Student(long sid, String sname, String gender, Date birthday, String address) { super(); this.sid = sid; this.sname = sname; this.gender = gender; this.birthday = birthday; this.address = address; } public long getSid() { return sid; } public void setSid(long sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
5.Student.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > <hibernate-mapping> <class name="org.hibernate.model.Student" table="STUDENT"> <id name="sid" type="java.lang.Long"> <column name="SID"/> <generator class="assigned"/><!-- 自定义主键 --> </id> <property name="sname" type="java.lang.String"> <column name="SNAME"/> </property> <property name="gender" type="java.lang.String"> <column name="GENDER"/> </property> <property name="birthday" type="java.util.Date"> <column name="BIRTHDAY"/> </property> <property name="address" type="java.lang.String"> <column name="ADDRESS"/> </property> </class> </hibernate-mapping>
6.HibernateTest.java
package org.hibernate.test; import java.sql.Connection; import java.sql.SQLException; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.jdbc.Work; import org.hibernate.model.Student; import org.junit.Test; public class HibernateTest { @Test public void testOpenSession() { Configuration config = new Configuration().configure();// 获取配置对象 SessionFactory sessionFactory = config.buildSessionFactory();// 获取SessionFactory对象 Session session1 = sessionFactory.openSession();// 获取Session对象 Session session2 = sessionFactory.openSession();// 获取Session对象 boolean result = session1 == session2; if (result) { System.out.println("openSession使用现有的session对象"); } else { System.out.println("openSession每次都创建新的session对象"); } } @Test public void testGetCurrentSession() { Configuration config = new Configuration().configure();// 获取配置对象 SessionFactory sessionFactory = config.buildSessionFactory();// 获取SessionFactory对象 Session session1 = sessionFactory.getCurrentSession();// 获取Session对象 Session session2 = sessionFactory.getCurrentSession();// 获取Session对象 boolean result = session1 == session2; if (result) { System.out.println("getCurrentSession使用现有的session对象"); } else { System.out.println("getCurrentSession每次都创建新的session对象"); } } @Test public void testSaveStudentWithOpenSession() { Configuration config = new Configuration().configure();// 获取配置对象 SessionFactory sessionFactory = config.buildSessionFactory();// 获取SessionFactory对象 Session session1 = sessionFactory.openSession();// 获取Session对象 Transaction transaction = session1.beginTransaction();// 开启事务 Student student = new Student(1, "张三", "男", new Date(), "北京");// 创建Student对象 session1.doWork(new Work() { public void execute(Connection connection) throws SQLException { System.out.println("connection hashCode: " + connection.hashCode()); } }); session1.save(student);// 保存对象 transaction.commit(); System.out.println(session1); Session session2 = sessionFactory.openSession();// 获取Session对象 transaction = session2.beginTransaction();// 开启事务 student = new Student(2, "李四", "男", new Date(), "上海");// 创建Student对象 session2.doWork(new Work() { public void execute(Connection connection) throws SQLException { System.out.println("connection hashCode: " + connection.hashCode()); } }); session2.save(student);// 保存对象 transaction.commit(); System.out.println(session2); } @Test public void testSaveStudentWithGetCurrentSession() { Configuration config = new Configuration().configure();// 获取配置对象 SessionFactory sessionFactory = config.buildSessionFactory();// 获取SessionFactory对象 Session session1 = sessionFactory.getCurrentSession();// 获取Session对象 Transaction transaction = session1.beginTransaction();// 开启事务 Student student = new Student(1, "张三", "男", new Date(), "北京");// 创建Student对象 session1.doWork(new Work() { public void execute(Connection connection) throws SQLException { System.out.println("connection hashcode: " + connection.hashCode()); } }); session1.save(student);// 保存对象 transaction.commit();// 提交事务 System.out.println(session1); Session session2 = sessionFactory.getCurrentSession();// 获取Session对象 transaction = session2.beginTransaction();// 开启事务 student = new Student(2, "李四", "男", new Date(), "上海");// 创建Student对象 session2.doWork(new Work() { public void execute(Connection connection) throws SQLException { System.out.println("connection hashcode: " + connection.hashCode()); } }); session2.save(student);// 保存对象 transaction.commit();// 提交事务 System.out.println(session2); } }
7.效果预览
7.1 执行testOpenSession()方法(通过openSession方法两次获取的session不一致,所以openSession每次都创建新的session对象)
7.2 执行testGetCurrentSession()方法(通过getCurrentSession方法两次获取的session一致,所以getCurrentSession使用现有的session对象)
7.3 执行testSaveStudentWithOpenSession()方法(两个session的哈希值是一样的,但是session都没有关闭;说明openSession不会自动关闭session,但是事务提交之后会自动关闭数据连接,因此第二个session使用的是第一个session关闭的数据库连接)
7.4 执行testSaveStudentWithGetCurrentSession()方法(两个session的哈希值是一样的,session都关闭了;说明getCurrentSession在事务提交后会自动关闭session,关闭数据连接,因此第二个session使用的是第一个session关闭的数据库连接)
9.总结
参考视频中说openSession获取的session不手动释放session,也就不会释放数据库连接。但是测试发现,openSession获取的session不会自动释放session,但是事务提交后会自动释放数据库连接。个人感觉只要提交事务后数据库连接都会被释放,session若是通过openSession获取的需手动关闭,若是通过getCurrentSession获取的则会在事务提交后自动释放