项目文件jar包(Hibernate1.rar)
hibernate路线图
Hibernate 简介(优点和缺点)
Hibernate 入门案例(基于XML的操作方式)
Hibernate 配置文件详解(基于xml的方式)
Hibernate 常用api介绍 (事务,回顾脏读,不可重复读(行级,读更改),幻读(表级读新增)以及数据库隔离级别.并发事务的解决悲观锁和乐观锁机制)
使用Hibernate框架完成 CRUD 操作
Hibernate 的对应关系详解(使用注解的方式进行配置,摘取一对多进行代码数据示例操作)
1.Hibernate 简介
同样的hibernate框架是基于jdbc轻量级进行的封装在这里我们再次提到一下这个叫做ORM(面向对象进行数据结构的设计)
面向对象进行数据结构的设计和数据库表的设计有什么不同
hibernate讲究的是全自动对象映射,与mybatis不同,mybatis讲究的是半自动映射
最先本质是为了解决java程序员设计对象的问题,是java的开发人员不关心数据库设计和范式定律
随着业务场景的复杂以及追求可插拔的高度自由化,当然同时也是为了以后springBoot中使用JPA做铺垫,hibernate中我们除了在初次使用的时候使用XML配置后,hibernate的级联关系操作我们采取使用注解的方式进行操作
准确的来说hibernate有的东西,mybatis也有.
2.Hibernate 入门案例(基于XML的操作方式)
1.构建一个新的项目(引入的jar包)
2.分别编写实体和对应的映射文件person.clas 和 pserson_hbm.xml
public class Person {
private int pid;
private String pname;
private Date bir;
}
//------------映射文件
<?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>
<!-- 映射哪一个实体类,以及表名 -->
<class name="com.wwj.model.Person" table="person">
<!-- 主键的生成策略采用自增 name为对象的属性-->
<id name="pid" column="pid">
<generator class="increment"></generator>
</id>
<property name="pname" column="pname"></property>
<property name="bir" column="bir"></property>
</class>
</hibernate-mapping>
3.编写全局声明配置文件 src下 (log4j保持最先的一致)
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-
3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 方言 保证控制台输出效果一致-->
<property name="dialect">
org.hibernate.dialect.MySQLDialect</property>
<!-- 数据库驱动jar包 -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!--显示sql语句是否格式化sql语句 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!--执行DDL的方式,create: 每一次运行都会覆盖原表中的内容 update: 保留原表中的内容 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 将我们的对象和表的映射文件加载到主配置文件中 -->
<mapping resource="com/wwj/model/Person_hbm.xml" />
</session-factory>
</hibernate-configuration>
4.构建操作,对比mybatis执行流程动作
/**
*
* @author wwj
* 1: 读取全局配置文件
* 2: 构建 sessionFactory
* 3: 创建 session(会话)
* 4: 开启transcation
* 5: 操作数据 (CRUD)
* 6: 提交事务 transcation
* 7: 关闭 session
*
*/
public class TestHT {
public static void main(String[] args) throws ParseException {
//先处理下时间
SimpleDateFormat sf1 = new SimpleDateFormat("yyyy-MM-dd");
String format = sf1.format(new Date());
Date parse = sf1.parse(format);
// 读取配置文件,实例化 默认的寻找 名字为 hibernate.cfg.xml
Configuration cfg = new Configuration().configure();
// 构建 session 工厂
SessionFactory sf = cfg.buildSessionFactory();
// 创建 session
Session session = sf.openSession();
// 操作数据 (insert delete update) 手动开启事务
Transaction bt = session.beginTransaction();
// 操作数据 (注意这里的面向对象操作)
Person per = new Person();
per.setPname("张三");
per.setBir(parse);
// CRUD操作
session.save(per);
// 提交事务
bt.commit();
session.close();
}
}
观察控制台的输出结果以及数据库表的结构
4. Hibernate常用api介绍
基本上大部分的框架都有一个叫做config的接口(使用xml解析填写的配置文件)
xxxFactory,万物皆有工厂造出来,不会平白无故的生成(工厂模式)
工厂虽然可以有很多,工厂很庞大,庞大就耗资源,所以我们才考虑对象的生成(单例模式)
(1)事务的ACID
原子性(Atomicity) 要么买要么就不买
一致性(Consistency)有买有卖,不能空仓打粮仓
隔离性(Isolation) 大家交易同一个物品的时候(互相又看不到)但是又不应该出现价格的相互影响(信息的壁垒)
持久性(Durability) 有迹可循,有记录
(2)事务并发
多个线程访问数据库同一条数据
脏读:一个事务读取到了另一个事务未提交的数据。
不可重复读(行级):一个事务范围内,两个相同的查询却得到了不同的结果。
幻读(表级):一个事务范围内,两个相同的查询却得到了不同的结果。
不可重复读发生点在一行上面,而幻读是发生在整张表上面
行级锁机制和表级锁都等同于操作上面仅且只有一个事务
补充说明:通过数据所提供的隔离级别(由低到高)
ISOLATION_READ_UNCOMMITTED:这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
ISOLATION_REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
ISOLATION_SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
重点说明 (Hibernate操作数据都是先查在操作)
悲观锁机制:也就是同步执行,一个一个来 查询语句加上for update
乐观锁: 使用版本号的机制
大家先查,看到的版本默认为1
做增加删除修改的时候在版本号上面加1 帅选条件要根据当前版本号 最后提交总有先后
有一个操作一定会发生异常,通过捕获异常来进行下一步的处理
5.使用 Hibernate 框架完成 CRUD 操作
public class TestHT {
public static void main(String[] args) throws ParseException {
//先处理下时间
SimpleDateFormat sf1 = new SimpleDateFormat("yyyy-MM-dd");
String format = sf1.format(new Date());
Date parse = sf1.parse(format);
// 读取配置文件,实例化 默认的寻找 名字为 hibernate.cfg.xml
Configuration cfg = new Configuration().configure();
// 构建 session 工厂
SessionFactory sf = cfg.buildSessionFactory();
// 创建 session
Session session = sf.openSession();
// 操作数据 (insert delete update) 手动开启事务
Transaction bt = session.beginTransaction();
// 操作数据
Person per = new Person();
per.setPname("张三");
per.setBir(parse);
// CRUD操作
// --1 .增加
session.save(per);
// --2 .查询 (如果查询多个,需要用到hql语句)
Person p = (Person) session.get(Person.class, 1);
// --3. 修改需要先查
p.setPname("小李");
session.update(p);
// -- 删除
session.delete(p);
// -- 查询所有
Query createQuery = session.createQuery("from Person");
List<Person> list = createQuery.list();
for(Person pp:list) {
System.out.println(pp.getPname());
}
// 提交事务
bt.commit();
session.close();
}
6.Hibernate的对应关系详解 (采用注解的方式)
1.一对一双向注解
Dad类
package com.wwj.onetoone;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
@Entity
public class Dad {
@Id
@GeneratedValue
private int did;
private String dadName;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="sonId",unique=true)
private Son son;
public int getDid() {
return did;
}
public void setDid(int did) {
this.did = did;
}
public String getDadName() {
return dadName;
}
public void setDadName(String dadName) {
this.dadName = dadName;
}
public Son getSon() {
return son;
}
public void setSon(Son son) {
this.son = son;
}
}
Son类
package com.wwj.onetoone;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
@Entity
public class Son {
@Id
@GeneratedValue
private int sid;
private String sname;
@OneToOne(mappedBy="son")
private Dad dad;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Dad getDad() {
return dad;
}
public void setDad(Dad dad) {
this.dad = dad;
}
}
2.一对多双向注解
Dad类
package com.wwj.onetomany;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
@Entity
public class Dad {
@Id
@GeneratedValue
private int did;
private String dadName;
@OneToMany(cascade=CascadeType.ALL,mappedBy="dad")
private List<Son> sons;
public int getDid() {
return did;
}
public void setDid(int did) {
this.did = did;
}
public String getDadName() {
return dadName;
}
public void setDadName(String dadName) {
this.dadName = dadName;
}
public List<Son> getSons() {
return sons;
}
public void setSons(List<Son> sons) {
this.sons = sons;
}
}
Son类
package com.wwj.onetomany;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
@Entity
public class Son {
@Id
@GeneratedValue
private int sid;
private String sname;
@ManyToOne
@JoinColumn(name="dadId")
private Dad dad;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Dad getDad() {
return dad;
}
public void setDad(Dad dad) {
this.dad = dad;
}
}
3.多对多双向注解
Dad类
package com.wwj.manytomany;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
@Entity
public class Dad {
@Id
@GeneratedValue
private int did;
private String dadName;
@ManyToMany(cascade = {CascadeType.ALL})
@JoinTable(name="dad_son",
joinColumns={@JoinColumn(name="did")},
inverseJoinColumns={@JoinColumn(name="sid")})
private List<Son> sons = new ArrayList<>();
public int getDid() {
return did;
}
public void setDid(int did) {
this.did = did;
}
public String getDadName() {
return dadName;
}
public void setDadName(String dadName) {
this.dadName = dadName;
}
public List<Son> getSons() {
return sons;
}
public void setSons(List<Son> sons) {
this.sons = sons;
}
}
son类
package com.wwj.manytomany;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
@Entity
public class Son {
@Id
@GeneratedValue
private int sid;
private String sname;
@ManyToMany
@JoinTable(name="dad_son",
joinColumns={@JoinColumn(name="sid")},
inverseJoinColumns={@JoinColumn(name="did")})
private List<Dad> dads;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public List<Dad> getDads() {
return dads;
}
public void setDads(List<Dad> dads) {
this.dads = dads;
}
}