初识Hibernate框架

本文深入探讨Hibernate框架,一种用于Java的持久层框架,对比Mybatis框架,详细解释了Hibernate的全ORM特性,无需手写SQL,以及它如何解决面向对象与关系型数据库之间的不匹配问题。文章还介绍了Hibernate的配置文件、命名规则、实体类映射和测试示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值