使用Hibernate完成数据持久化
-了解Hibernate的基本原理
-学会编写实体配置文件
-熟练掌握使用Hibernate进行增删改查操作
-掌握在项目中使用Hibernate
为什么使用Hibernate?
代码精简易读
封装了JDBC操作,以面向对象的方式操作数据
开发工作量小,可以将精力集中在业务逻辑处理上
什么是Hibernate?
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,对数据持久化的工具。
HIbernate之父--------Gaving King
ORM:完成对象数据到关系型数据的映射的机制成为对象-关系映射
什么是数据持久化?
持久化过程中有三个状态:瞬时状态、持久状态、游离状态
持久化:将程序数据在瞬时状态与持久状态之间转换的机制。
瞬时状态:保存在内存中的程序数据,程序退出后,数据就消失了,称为瞬时状态。
持久状态:保存在磁盘上的程序数据,程序退出后依然存在,称为程序数据的持久状态。
使用Hibernate的3个准备:
(1)导入Hibernate jar包
(2)添加配置文件hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
<!-- 配置数据源 -->
<session-factory>
<!-- 使用C3P0替换数据源 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- 最大连接数 -->
<property name="hibernate.c3p0.max_size">50</property>
<!-- 最小连接数 -->
<property name="hibernate.c3p0.min_size">10</property>
<!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->
<property name="hibernate.c3p0.timeout">2000</property>
<!-- 最大的PreparedStatement的数量 -->
<property name="hibernate.c3p0.max_statements">100</property>
<!-- 每隔120秒检查连接池里的空闲连接 ,单位是秒-->
<property name="hibernate.c3p0.idle_test_period">60</property>
<!-- 当连接池里面的连接用完的时候,C3P0一下获取的新的连接数 -->
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:niit</property>
<property name="hibernate.connection.username">system</property>
<property name="hibernate.connection.password">niit</property>
<!-- 配置数据库方言 -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="show_sql">true</property>
<!-- 添加映射文件 -->
<mapping resource="com/niit/mapper/userMapper.xml"/>
<mapping resource="com/niit/mapper/empMapper.xml"/>
<mapping resource="com/niit/mapper/depMapper.xml"/>
<mapping resource="com/niit/mapper/customerMapper.xml"/>
<mapping resource="com/niit/mapper/orderMapper.xml"/>
</session-factory>
</hibernate-configuration>
(3)添加实体类和映射文件
public class User implements Serializable {
private int userId;
private String userName;
private String password;
private Date regTime;
private int sex;
public User(){}
public User(int userId, String userName, String password, Date regTime,
int sex) {
super();
this.userId = userId;
this.userName = userName;
this.password = password;
this.regTime = regTime;
this.sex = sex;
}
public User(String userName, String password){
this.userName = userName;
this.password = password;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getRegTime() {
return regTime;
}
public void setRegTime(Date regTime) {
this.regTime = regTime;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.niit.pojo">
<!-- 配置实体类与数据表的映射关系 -->
<class name="User" table="users">
<!-- 映射主键 -->
<id name="userId" column="userid"></id>
<!-- 映射其他字段 -->
<property name="userName" column="username"></property>
<property name="password" column="userpwd"></property>
<property name="regTime" column="regtime"></property>
<property name="sex" column="sex"></property>
</class>
</hibernate-mapping>
使用Hibernate的7个步骤:
public static void main(String[] args) {
// TODO Auto-generated method stub
//(1)启动Hibernate框架,加载配置文件
Configuration config = new Configuration().configure();
//(2)创建SessionFactory
SessionFactory factory = config.buildSessionFactory();
//(3)打开Session,获得数据库连接
Session session = factory.openSession();
//(4)开启事务,数据持久化必须开启事务
Transaction transaction = session.beginTransaction();
//(5)持久化操作
//创建User对象
//此时对象状态为瞬时状态,和数据表没有关联
User user = new User(1, "jack", "jack123", new Date(), 1);
//保存对象至数据库
//session.save(user);
//此时对象状态为持久化状态,在事务未提交之前,对象的任意改变都将关联影响到数据库
//user.setPassword("admin_123");
//(6)提交事务
transaction.commit();
//事务提交后,对象状态未游离状态
//user.setUserName("jack");
//(7)关闭Session
session.close();
}
根据主键进行查询
查询不需要开始事务
public static void main(String[] args) {
Configuration config = new Configuration().configure();
SessionFactory factory = config.buildSessionFactory();
Session session = factory.openSession();
//进行查询不需要开启事务
//根据主键查询
//load查询
User user = (User) session.load(User.class, 1);
session = factory.openSession();
//get查询
User user1 = (User) session.get(User.class, 1);
//关闭
session.close();
System.out.println(user1.getClass());
System.out.println(user.getUserName());
}
get与load方法查询后的结果都将写入缓存
* get与load的差异:
* 1.get如果查找不到数据返回null,load查找不到数据则抛出异常
* 2.load首先至缓存中加载查找的数据,如果缓存中不存在,则到数据库中查询对应的数据,并返回数据映射对象的代理类;get也先至缓存中查询数据
* 如果数据不存在,则至数据库中查询数据并返回对象本身
Hibernate的缓存
缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为了减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能。
(
基本上我们开发项目只会用到一级缓存,如果是大项目可能会用到二级缓存)
HIbernate一级缓存
session是Hibernate的一次缓存区域,存储根据ID查询获取的对象包,可以通过get和load方法从缓存中获取数据。
Hibernate二次缓存
sessionFactory缓存分为内置缓存和外置缓存,其中sessionFactory的外置缓存称为二级缓存,需要通过插件的方式来开启。
sessionFactory内置缓存存储了映射的元数据和预定义SQL语句,外置缓存是进程级缓存,被全局共享,用以存储需要频繁读取且具有稳定性的数据。
二级缓存的使用原则:
(1) 更新频率低的数据
(2)不会被第三方改变的数据
(3)非关键数据(如财务数据)
(4)数据大小在内存可接受范围内的数据
二级缓存的使用步骤:
(1)把ehcache-1.2.3.jar加入到当前应用的classpath中
(2)在hibernate.cfg.xml文件中加入EhCache缓存插件的提供类
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider
</property>
(3)配置持久化类的对象关系映射文件
<hibernate-mapping>
<class name="pojo.Student" table="student" catalog="system">
<!-- 配置启用Student对象的缓存 -->
<cache usage="read-only"/>
<id name="stuId">
<column name="stuId"></column>
</id>
<property name="stuName">
<column name="stuName"></column>
</property>
</class>
</hibernate-mapping>
Hibernate本身数据池的性能不是很好,因此可以通过配置文件替换数据池。
配置JNDI数据源
<property name="connection.datasource">java:comp/env/jndi/mysource</property>
配置C3P0数据池
<!-- 配置数据源 -->
<session-factory>
<!-- 使用C3P0替换数据源 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- 最大连接数 -->
<property name="hibernate.c3p0.max_size">50</property>
<!-- 最小连接数 -->
<property name="hibernate.c3p0.min_size">10</property>
<!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->
<property name="hibernate.c3p0.timeout">2000</property>
<!-- 最大的PreparedStatement的数量 -->
<property name="hibernate.c3p0.max_statements">100</property>
<!-- 每隔120秒检查连接池里的空闲连接 ,单位是秒-->
<property name="hibernate.c3p0.idle_test_period">60</property>
<!-- 当连接池里面的连接用完的时候,C3P0一下获取的新的连接数 -->
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:niit</property>
<property name="hibernate.connection.username">system</property>
<property name="hibernate.connection.password">niit</property>
<!-- 配置数据库方言 -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="show_sql">true</property>
<!-- 添加映射文件 -->
<mapping resource="com/niit/mapper/userMapper.xml"/>
<mapping resource="com/niit/mapper/empMapper.xml"/>
<mapping resource="com/niit/mapper/depMapper.xml"/>
<mapping resource="com/niit/mapper/customerMapper.xml"/>
<mapping resource="com/niit/mapper/orderMapper.xml"/>
</session-factory>