Hibernate框架是一种持久层框架, 功能类似于 Mybatis 框架
与 Mybatis框架对比:
(1) Mybatis是 半 ORM框架, 需要手写SQL ;
而Hibernate 是 全 ORM框架 , 无需手写SQL, SQL由框架自动生成
(2) Mybatis 本质上仍然是 开发人员直接对 数据库表进行 操作
而 Hibernate 将 原先对表的 操作 转换成了 纯粹的对 类 和对象的 操作
Hibernate 消除了 面向关系型数据库操作 和 面向对象 操作 的 不匹配 问题 , 更符合 面向对象开发 的特点
(3) 用Mybatis 框架 开发时,需要考虑 采用何种数据库 , 手写的SQL需要紧密结合具体的某个数据库产品(MySQL,Oracle,SQLServer,DB2)
而hibernate 与 具体的数据库产品类型无关 , 可以方便地实现 项目 由 原先基于的某种数据库 向 另一种数据库的 迁移 , DAO层代码无需修改
(4) Hibernate 根据 对类 和对象的操作 所自动生成的SQL 语句 比较固定, 不如 Mybatis框架 手写的 SQL灵活 , 不利于做SQL 优化改良
学习框架的 重点在于 学习 xml 配置规则*
使用hibernate框架需要jar包支持
命名规则:
总配置文件:名称-- hibernate.cfg.xml
实体类映射配置文件-- Xxxx.hbm.xml(Xxxx为实体类 类名,hbm是 hibernateMap缩写)
1:Hibernate的主配置文件的名字必须是hibernate.cfg.xml(如果名称有错误,测试时可能会出现错误,框架找不到主配置)(主要配置文件中主要配置:数据库连接信息,其他参数,映射信息):
1.1:主配置文件主要分为三部分:
注意:通常情况下,一个session-factory节点代表一个数据库;
1.1.1:第一部分
数据库连接部分,注意"hibernate.connection.driver_class"中间的 _(杠);
1.1.2:第二部分
其他相关配置,包含打印sql语句,格式化sql语句,创建数据表或者更新数据表等等
1.1.3:第三部分
加载所有的映射;
看一下具体的代码演示:
主配置文件: hibernate.cfg.xml----在src目录下
<?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">
<session-factory>
<!-- Database connection settings --><!-- 设置数据库连接 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url"><![CDATA[jdbc:mysql://localhost:3306/emp?useUnicode=true&characterEncoding=UTF-8]]></property>
<property name="connection.username">root</property>
<property name="connection.password">123</property>
<!-- SQL dialect -->
<!-- 数据库方言 确定哪种数据库语言--这里使用的是数据库是 mysql-->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- Echo all executed SQL to stdout --><!-- 标准输出sql语句 -->
<!-- 展示 sql 语句 -->
<property name="show_sql">true</property>
<!-- sql语句 格式化显示 -->
<property name="format_sql">true</property>
<!-- 实体类映射文件路径 -->
<mapping resource="entity/emp.hbm.xml" />
</session-factory>
映射文件: emp.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">
<class name="Emp" table="emp">
<id name="empno" column="empno" type="int">
<generator class="increment"></generator>
</id>
<!--java实体类中的属性, column--数据库中的字段名,类型也需要指出,这样会更快,更准确-->
<property name="ename" column="ename" type="java.lang.String" />
<property name="sal" column="sal" type="double" />
<property name="job" column="job" type="java.lang.String" />
<property name="comm" column="comm" type="double" />
<property name="hiredate" column="hiredate" type="java.lang.String" />
<property name="mgr" column="mgr" type="int" />
</class>
实体类:Emp
package entity;
public class Emp {
private int empno;
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
private String ename;
private String job;
private double sal;
private int mgr;
private String hiredate;
private double comm;
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public Emp(){
super();
}
//不可添加有参构造,需要先将无参构造创建-->框架默认调用无参构造
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public String getHiredate() {
return hiredate;
}
public void setHiredate(String hiredate) {
this.hiredate = hiredate;
}
public Emp(String ename, String job, double sal, int mgr, String hiredate, double comm) {
super();
this.ename = ename;
this.job = job;
this.sal = sal;
this.mgr = mgr;
this.hiredate = hiredate;
this.comm = comm;
}
public double getComm() {
return comm;
}
public void setComm(double comm) {
this.comm = comm;
}
public void setComm(int comm) {
this.comm = comm;
}
}
测试类:该测试类中囊括了简易的Hiberbate框架中的增删查改
package test;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import entity.Emp;
import util.DateUtil;
import util.HibernateUtil;
public class TestEmp {
@Test
public void testEmp() {
//从默认路径下 加载并解析 hibernate 总配置文件 hibernate.cfg.xml
Configuration conf = new Configuration().configure();
//构建 会话工厂
SessionFactory sf = conf.buildSessionFactory();
// 打开一个(数据库)会话
Session session = sf.openSession();
//根据员工主键值,查询员工信息
Emp emp = (Emp) session.load(Emp.class, 7788);
System.out.println("姓名:"+emp.getEname() +" 工资:"+ emp.getSal()+" 入职日期:"+emp.getHiredate()+" 奖金:"+emp.getComm());
//关闭会话
session.close();
}
@Test
//这种方法采用的是 工具类,将连接的的部分代码写成工具类,可简化代码
public void testEmp2() {
Session session = HibernateUtil.getSession();
Emp emp = (Emp) session.load(Emp.class, 7788);
System.out.println("姓名:"+emp.getEname() +" 工资:"+ emp.getSal()+" 入职日期:"+emp.getHiredate()+" 奖金:"+emp.getComm());
//关闭会话
HibernateUtil.closeSession();
}
@Test
//测试向数据库插入数据
public void testInsert(){
Session session = HibernateUtil.getSession();
Emp emp = new Emp("majun","ceo",50000,520,DateUtil.dateToString(new Date()),2000);
/*Emp emp = new Emp();
emp.setComm(1000);
emp.setEname("majunyi2");
emp.setJob("CEO");
emp.setHiredate(DateUtil.dateToString(new Date()));*/
//开始事务
Transaction tx = session.beginTransaction();
int id = (int) session.save(emp);//持久化 Emp对象到 数据库
tx.commit();//提交事务
HibernateUtil.closeSession();//关闭会话
}
// 测试删除
@Test
public void testDeleteEmp() {
// 创建会话
Session session = HibernateUtil.getSession();
Emp emp = new Emp();// 创建一个对象
emp.setEmpno(8909);// 设置对象的主键值
Transaction tx = session.beginTransaction();// 构建会话工厂
session.delete(emp);// 删除emp对象和其所有的值
tx.commit();// 提交事务
HibernateUtil.closeSession();// 关闭会话(连接)
}
/*
* 测试更新(两种方案) 将新创建的对象所赋予的值覆盖掉原来的值 (必须将数据库所有字段都设值,否则数据库中会出现字段类型默认的值(0或null))
*/
@Test
public void testUpdateEmp() {
Session session = HibernateUtil.getSession();
Emp emp = new Emp();
emp.setEmpno(8908);
emp.setEname("赵武");
emp.setHiredate(DateUtil.dateToString(new Date()));
emp.setComm(5000);
emp.setJob("经理");
emp.setSal(90000);
Transaction ts = session.beginTransaction();// 构建会话工厂
session.update(emp);
ts.commit();
HibernateUtil.closeSession();
}
/*这种更新方法是
* 先加载数据库中的数据,再原有数据的基础上修改 部分字段
* 比如:修改一个密码(仅需要修改密码,那么之前所有的数据信息都不需要更改--->在原有的数据上修改密码)
* */
@Test
public void testUpdateEmp2() {
Session session = HibernateUtil.getSession();
Emp emp = new Emp();
emp = (Emp) session.load(Emp.class, 8907);
emp.setEname("李四");
Transaction ts = session.beginTransaction();
session.update(emp);
ts.commit();
HibernateUtil.closeSession();
}
}
工具类:
package util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
// 初始化一个ThreadLocal对象
private static final ThreadLocal<Session> sessionTL = new ThreadLocal<Session>();
private static Configuration configuration;
private final static SessionFactory sessionFactory;
static {
try {
configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static Session getSession() {
//sessionTL的get()方法根据当前线程返回其对应的线程内部变量,
//即我们需要的Session,多线程情况下共享数据库连接是不安全的。
//ThreadLocal保证了每个线程都有自己的Session对象。
Session session = (Session) sessionTL.get();
// 如果session为null,则打开一个新的session
if (session == null) {
//创建一个数据库连接对象session。
session = sessionFactory.openSession();
// 保存该数据库连接session到ThreadLocal中。
sessionTL.set(session);
}
//如果当前线程已经访问过数据库了,
//则从sessionTL中get()就可以获取该线程上次获取过的数据库连接对象。
return session;
}
/**
* 关闭Session
*/
public static void closeSession(){
Session session = (Session) sessionTL.get();
sessionTL.set(null);
session.close();
}
}
时间工具类:
package util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期工具类
* @author QPH
*
*/
public class DateUtil {
private static final SimpleDateFormat SDF_DATE = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat SDF_DATE_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static String dateTimeToString(Date date) {
return SDF_DATE_TIME.format(date);
}
public static Date stringToDateTime(String dateStr) throws ParseException {
return SDF_DATE_TIME.parse(dateStr);
}
public static String dateToString(Date date) {
return SDF_DATE.format(date);
}
public static Date stringToDate(String dateStr) throws ParseException {
return SDF_DATE.parse(dateStr);
}
}