栖梧桐 2020-02-21
Hibernate是使用在三层架构中的dao层的一个轻量级框架,与JDBC和myBatis是类似的技术,它也是基于ORM(对象关系映射:数据表中的字段和实体类中的属性一一对应)设计的,其实就是对JDBC的封装,封装之后的东西使用起来更加方便快捷。
Hibernate是一个全自动的ORM框架,全自动代表数据表,SQL语句会自动生成,弊端在于不够灵活,效率低,而myBatis是一个半自动的ORM框架,mybatis可以自己写sql语句,相对来说比较灵活,所以国内大多数开发者更青睐于使用myBatis。
Gavin King,详情见百度百科
1.无需编写SQL,操作面向对象,提高生产效率
2.开发对象化
3.移植性好(更换数据库时,只需更改相应配置文件)
4.透明持久化(对象无需继承框架任何类或接口)
5.轻量级框架(无侵入性)
6.测试方便
下面我们通过具体事例来了解hibernate的工作原理和实现步骤:
开发工具:Intellij idea
数据库:mysql
具体步骤如图所示:
1.新建Project(此处以创建web项目为例)
勾选Web Application + Hibernate同时勾选 ”Create default hibernate configuration and main class”(当然也可以不勾选,在项目创建好后再手动创建也是一样的)
2.点击next,填写项目名称,finish,完成后项目结构如图所示:
IDEA已经帮我们创建好了hibernate.cfg.xml文件、导入了相应的jar包,但需要注意的是mysql jdbc驱动jar包是需要自己自己手动添加的(其他的都为建项目的时候自动生成),注意jdbc版本,太高会出错,很头疼的一个问题。
下载mysql的jar包的方法可以参考:
https://www.cnblogs.com/NyanKoSenSei/p/11510438.html
在连接数据库之前,需创建好数据库)找到Database,点击如图所示:
填写Database(数据库名)、User(用户名)、Password(当前用户密码)
点击“Test Connection”测试连接成功,点击“Apply”,点击OK
连接成功
例如tudentEntity.hbm.xml,与StudentEntity代码(此段代码为根据数据库结构自动生成的),如图所示:
1.选择Persistence
2.继续如下操作
选中如图所示的选项后,点击ok,xml和实体类就自动生成了,如图所示:
3.1 StudentEntity.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="com.example.StudentEntity" table="student" schema="test">
<id name="sid" column="sid"/>
<property name="name" column="name"/>
<property name="birthday" column="birthday"/>
<property name="sex" column="sex"/>
</class>
</hibernate-mapping>
3.2 StudentEntity代码:
package com.example;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "student", schema = "test", catalog = "")
public class StudentEntity {
private int sid;
private String name;
private Date birthday;
private String sex;
@Id
@Column(name = "sid")
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
@Basic
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Basic
@Column(name = "birthday")
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Basic
@Column(name = "sex")
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
StudentEntity that = (StudentEntity) o;
if (sid != that.sid) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
if (birthday != null ? !birthday.equals(that.birthday) : that.birthday!= null) return false;
if (sex != null ? !sex.equals(that.sex) : that.sex != null) return false;
return true;
}
@Override
public int hashCode() {
int result = sid;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (birthday != null ? birthday.hashCode() : 0);
result = 31 * result + (sex != null ?
sex.hashCode(): 0);
return result;
}
}
<?xml version=‘1.0‘ encoding=‘utf-8‘?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-
3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--配置数据库通信-->
<property name="connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!--配置数据库方言-->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="show_sql">true</property><!--为了让hinbernate输出执行的底层的sql语句-->
<property name="format_sql">true</property><!--让输出的底层执行的sql语句有一定的格式-->
<!--指定自动生成数据表的策略 -->
<property name="hbm2ddl.auto">update</property> <!--自动创建|更新|验证数据库表结构-->
<mapping resource="com/example/StudentEntity.hbm.xml"/><!--引入实体类配置文件-->
<mapping class="com.example.StudentEntity"/><!--引入实体类位置-->
</session-factory>
</hibernate-configuration>
5.测试
写测试类:StudnetTest.java 代码:
package com.example.test;
import com.example.StudentEntity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StudentTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
//插入数据
@Test
public void testisnert() {
System.out.println("test....");
//创建配置对象(读取配置文档)
Configuration config = new Configuration() .configure();
//创建会话工厂对象
sessionFactory = config.buildSessionFactory();
//会话对象
session = sessionFactory.openSession();
//开启事务
transaction = session.beginTransaction();
StudentEntity studentEntity = new StudentEntity();
studentEntity.setName("王五");
try {
Date birthday=new SimpleDateFormat("yyyy-MM-dd").parse("2000-11-11");
studentEntity.setBirthday(birthday);
} catch (ParseException e) {
e.printStackTrace();
}
studentEntity.setSex("男");
session.save(studentEntity);
//提交事务
transaction.commit();
//关闭事务
session.close();
sessionFactory.close();
}
//更新数据
@Test
public void testupdate() {
System.out.println("test....");
//创建配置对象(读取配置文档)
Configuration config = new Configuration().configure();
//创建会话工厂对象
sessionFactory = config.buildSessionFactory();
//会话对象
session = sessionFactory.openSession();
//开启事务
transaction = session.beginTransaction();
StudentEntity studentEntity = new StudentEntity();
studentEntity.setSid(0007);
studentEntity.setName("李四");
try {
Date birthday=new SimpleDateFormat("yyyy-MM-dd").parse("2000-11-11");
studentEntity.setBirthday(birthday);
} catch (ParseException e) {
e.printStackTrace();
}
studentEntity.setSex("男");
session.update(studentEntity);
//提交事务
transaction.commit();
//关闭事务
session.close();
sessionFactory.close();
}
//删除数据
@Test
public void testdelete(){
System.out.println("test....");
//创建配置对象(读取配置文档)
Configuration config = new Configuration().configure();
//创建会话工厂对象
sessionFactory = config.buildSessionFactory();
//会话对象
session = sessionFactory.openSession();
//开启事务
transaction = session.beginTransaction();
StudentEntity studentEntity = session.get(StudentEntity.class, 0006);
session.delete(studentEntity);
//提交事务
transaction.commit();
//关闭事务
session.close();
sessionFactory.close();
}
//查询数据
@Test
public void testselect(){
System.out.println("test....");
//创建配置对象(读取配置文档)
Configuration config = new Configuration().configure();
//创建会话工厂对象
sessionFactory = config.buildSessionFactory();
//会话对象
session = sessionFactory.openSession();
//开启事务
transaction = session.beginTransaction();
StudentEntity studentEntity = session.get(StudentEntity.class, 0001);
System.out.println(studentEntity.getSid()+""+studentEntity.getName()+""+studentEntity.getBirthday()+""+studentEntity.getSex());
//提交事务
transaction.commit();
//关闭事务
session.close();
sessionFactory.close();
}
}
控制台查询数据运行结果如图所示:
数据表内容如图所示:
至此,hibernate的实例基本结束了,下面我们来总结下知识点:
1.hibernate的开发步骤:
1)搭建好环境
引入hibernate最小的jar包
准备Hibernate.cfg.xml启动配置文件
2)写实体类(pojo)
3)为实体类写映射文件"User.hbm.xml"
在hibernate.cfg.xml添加映射的实体
4)创建库表
5)写测试类
获得Configuration
创建SessionFactory
打开Session
开启事务
使用session操作数据
提交事务
关闭资源
2.hibernate的工作原理:
1)通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2)由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>读取并解析映射信息
3)通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
4)Session session = sf.openSession();//打开Sesssion
5)Transaction tx = session.beginTransaction();//创建并启动事务Transation
6)persistent operate操作数据,持久化操作
7)tx.commit();//提交事务
8)关闭Session
9)关闭SesstionFactory
3. Hibernate的缓存机制:
Hibernate缓存的作用:
Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据
Hibernate缓存分类:
Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存
Hibernate一级缓存又称为“Session的缓存”,它是内置的,意思就是说,只要你使用hibernate就必须使用session缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每个实例都具有唯一的OID。
Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。
什么样的数据适合存放到第二级缓存中?
1 很少被修改的数据
2 不是很重要的数据,允许出现偶尔并发的数据
3 不会被并发访问的数据
4 常量数据
不适合存放到第二级缓存的数据?
1 经常被修改的数据
2 绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发
3 与其他应用共享的数据。