本文仅用于自我学习总结,无任何高深代码,大佬绕行,多多见谅!
1.概念
1.1 ORM
什么是框架:简单来说就是大师写好的半成品,已经具有部分功能
什么是ORM: ORM是一种思想,ORM (全称为 :Object Relative Mapping)对象-关系映射;它的作用是在关系型数据库
和业务实体对象之间作一个映射,简化了数据库查询过程。使用ORM查询工具,用户可以访问期望数据,而不必理解数据库的底层结构。
简单来说就是ORM可以实现利用对象操纵数据库中的表。
1.2 模型:
java是域模型:面向对象:类和对象来描述和存储数据
sql是关系模型:二维表和行描述和存储数据
1.表之间的关系分为
- 1对n :在n表中定义外键 来引用1表的主键列
- 1对1 :根据主次/先后顺序 区分主表和从表 把从表的主键列 同时定义为外键 来引用主表的主键列
- n对n : 定义个关系表 其中定义两列作为联合主键 这两列同时定义为外键 来分别引用两个主表的主键列
2.类与类之间的关系(域模型)
- 关联关系: 订单和客户 :订单要指定其所属客户 (部分依赖)
- 聚集关系: 轮胎和车 : 轮胎是车的一部分 (整体和部分)
- 依赖关系: action和service: action中所有方法都要通过service来实现 (类似于寄生)
- 一般化关系: 儿子和父亲:继承关系
1.3 什么是Hibernate:
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用面向对象编程思维来操纵数据库
2. hibernate初次体验
2.1 创建java项目
2.2 引入依赖
-
在src下创建一个文件夹lib
-
复制依赖
-
右键点击Add as Library
-
2.3 创建hibernate的属性集文件
文件位置:必须是src
文件名字:必须是hibernate.properties
# 定义链接数据库的四大参数
# 指定方言
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/db_1
hibernate.connection.username=root
hibernate.connection.password=562412
# 显示sql
hibernate.show_sql=true
2.4 根据表创建实体类
-
表
CREATE TABLE `student` (
`sid` int(11) NOT NULL AUTO_INCREMENT,
`sname` varchar(11) NOT NULL,
`score` float(4,1) DEFAULT NULL,
`sex` char(1) DEFAULT NULL,
`sage` int(11) DEFAULT NULL,
`sphoto` varchar(100) DEFAULT '0.jpeg',
PRIMARY KEY (`sid`),
UNIQUE KEY `sname` (`sname`)
) ENGINE=InnoDB AUTO_INCREMENT=220 DEFAULT CHARSET=utf8
-
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain=true)
public class Student implements Serializable {
private Integer id;
private String name;
private String sex;
private Float score;
private String photo;
private Integer age;
}
2.5 创建实体类的mapper映射文件
指定表和类对应关系::以及表中列和类中属性的对应关系 必须和实体类在同一个文件夹中 名字必须是类名.hbm.xml hibernate mapper缩写为hbm
<?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="test01.Student" table="student">
<!-- 指定主键列对应的属性 -->
<id name="id" column="sid" type="int">
<generator class="identity"/><!-- 主键自增方式:数据库自增-->
</id>
<!--非主键对应的属性-->
<property name="name" column="sname" type="string"></property>
<property name="age" column="sage"/>
<property name="sex" column="sex"/>
<property name="score" column="score"/>
<property name="photo" column="sphoto"/>
</class>
</hibernate-mapping>
2.5 启动类
public class Test01 {
public static void main(String[] args) {
//1 创建configer对象 读取核心配置文件
Configuration config=new Configuration();
//2 指定加载mapper映射文件
config.addClass(Student.class);
//3 获取sessionFactory对象
SessionFactory factory=config.buildSessionFactory();
//4 获取session对象
Session session = factory.openSession();
//5 获取事务
Transaction transaction = session.beginTransaction();
// 6开启事务
transaction.begin();
//7 执行crud
//7.1 获取一个
Student s1 = (Student) session.get(Student.class, 91);
Student s2 = (Student) session.load(Student.class, 92);
//7.2 获取所有:::query接口:::hql::::把sql的表名更改为类名 把列名更改为属性名
Query query = session.createQuery("from test01.Student where age > 18");
List<Student> list = query.list();
//7.3 修改一个
s1.setAge(s1.getAge()+10);
s1.setName(s1.getName()+"同志");
session.update(s1);
//7.4 添加一个
Serializable id = session.save(new Student().setPhoto("01.jpg").setAge(11).setName("呵呵呵01").setScore(11f).setSex("妖"));
System.out.println("id="+id);
//7.5 删除一个
session.delete(s2);
//8 关闭事务
transaction.commit();
//9 关闭连接 释放资源
session.close();
factory.close();
}
}
3 hibernate的xml配置文件
与上面只有两处不同
1 不再创建属性集文件 而是创建xml文件
2 Configuration对象不需要addClass指定加载所有的mapper映射文件 而是加载hibernate的xml核心配置文件即可
3.1 创建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>
<!-- 指定方言 -->
<!--hibernate.dialect=org.hibernate.dialect.MySQLDialect-->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 指定连接的四大参数 -->
<!--
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/db_1
hibernate.connection.username=root
hibernate.connection.password=root
-->
<property name="connection.url">jdbc:mysql://localhost:3306/db_1</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">562412</property>
<!-- 是否显示sql语句 -->
<!--hibernate.show_sql=true-->
<property name="show_sql">true</property>
<!-- 导入类与表的映射文件 -->
<mapping resource="test02/Student.hbm.xml" />
</session-factory>
</hibernate-configuration>
3.2 启动类
//1 创建configer对象 读取核心配置文件
Configuration config=new Configuration();
//2 指定加载mapper映射文件
//config.addClass(test02.Student.class);
//2 记载指定的核心配置文件
config.configure("test02/hibernate.cfg.xml");
4 load和get的区别
相同之处:都是通过主键获取一个对象
不同之处:
1. get是立即加载::get一旦调用就立刻执行sql语句
load是懒加载::load调用时 获取的空的代理对象::当第一次使用此代理对象
2. get方法参数主键值不存在时 返回null
load方法参数主键值不存在时 抛出异常ObjectNotFoundException
注意:session关闭后 如果是第一次使用load获取的对象 会报错LazyInitializationException
5 hibernate的id自增方式/自增策略
id标签用于指定表的主键列和类中属性的对应关系 generator标签用于指定id的自增方式
- identity:数据库自增:id列需要添加约束auto_increment
- increment:hibernate自增:hibernate在服务器内存中定义一个变量记录id的最大值
- sequence:序列自增:适用于支持序列的数据库 oracle、sqlserver
- uuid:适用于字符串类型的主键:生成一个32位的随机字符串
- Hilo:高低位:需要第一个一个单独的表记录id的最大值 assigned:手动赋值
- native:根据数据库特点自动选择sequence、identity、hilo
- foreign:适用于1对1表关系时
5.1 identity:数据库自增
数据库自增:identity:数据库自增
-
sql
CREATE TABLE demo01(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(100)
);
INSERT INTO demo01 VALUES(111,"呵呵11");
-
mapper映射文件
<class name="test03.Demo01" table="demo01">
<!-- 指定主键列对应的属性 -->
<id name="id" column="id" type="int">
<generator class="identity"/><!-- 主键自增方式:数据库自增::auto_increment-->
</id>
<!--非主键对应的属性-->
<property name="name" column="name" />
</class>
-
启动类
//测试添加
System.out.println("添加一个:::"+session.save(new Demo01(1234,"呵呵1234")));
System.out.println("添加一个:::"+session.save(new Demo01(null,"呵呵12345")));
-
打印的日志信息
Hibernate: insert into demo01 (name) values (?)
添加一个:::112
Hibernate: insert into demo01 (name) values (?)
添加一个:::113
5.2 increment:hibernate自增
hibernate在服务器内存中定义一个变量记录id的最大值 不适用多线程和分布式项目
-
sql
CREATE TABLE demo02(
id INT PRIMARY KEY,
NAME VARCHAR(100)
);
INSERT INTO demo02 VALUES(111,"呵呵11");
-
mapper映射文件
<!-- 指定类名 和 表名 -->
<class name="test03.Demo02" table="demo02">
<!-- 指定主键列对应的属性 -->
<id name="id" column="id" type="int">
<!--<generator class="identity"/>--><!-- 主键自增方式:数据库自增::auto_increment-->
<generator class="increment"/><!--主键自增方式:hibernate自增-->
</id>
<!--非主键对应的属性-->
<property name="name" column="name" />
</class>
-
启动类
//测试添加
System.out.println("添加一个:::"+session.save(new Demo02(1234,"呵呵1234")));
System.out.println("添加一个:::"+session.save(new Demo02(null,"呵呵12345")));
-
打印的日志信息
Hibernate: select max(id) from demo02 # 先访问数据库获取id的最大值 使用hibernate的内存一个变量记录此值
添加一个:::112
添加一个:::113
Hibernate: insert into demo02 (name, id) values (?, ?)
Hibernate: insert into demo02 (name, id) values (?, ?)
5.3 hilo:高低位
需要定义另外一张表 记录当前表的主键的最大值
-
sql
-- hilo高低位
CREATE TABLE demo03(
id INT PRIMARY KEY,
NAME VARCHAR(100)
);
INSERT INTO demo03 VALUES(111,"呵呵11");
-- 定义一个表:记录demo03的主键的最大值
CREATE TABLE demo03_hilo(
hilo_value INT
);
-- 字段hilo_value必须先初始化一个值
INSERT INTO demo03_hilo VALUES(1000);
-
mapper映射文件
<!-- 指定类名 和 表名 -->
<class name="test03.Demo03" table="demo03">
<!-- 指定主键列对应的属性 -->
<id name="id" column="id" type="int">
<!--<generator class="identity"/>--><!-- 主键自增方式:数据库自增::auto_increment-->
<!--<generator class="increment"/>--><!--主键自增方式:hibernate自增-->
<generator class="hilo">
<param name="table">demo03_hilo</param><!--数据库中主键发生表-->
<param name="column">hilo_value</param><!--主键发生所在字段,必须初始化,即有一条记录设置了初始值-->
<param name="max_lo">0</param><!--高位连接数字-->
</generator>
</id>
<!--非主键对应的属性-->
<property name="name" column="name" />
</class>
-
启动类
System.out.println("添加一个:::"+session.save(new Demo03(1234,"呵呵1234")));
System.out.println("添加一个:::"+session.save(new Demo03(null,"呵呵12345")));
-
打印的日志信息
添加一个:::1000
添加一个:::1001
Hibernate: insert into demo03 (name, id) values (?, ?)
Hibernate: insert into demo03 (name, id) values (?, ?)
5.4 uuid:随机字符串
针对于字符串类型的主键
-
sql
-- uuid随机字符串
CREATE TABLE demo04(
id VARCHAR(100) PRIMARY KEY,
NAME VARCHAR(100)
);
INSERT INTO demo04 VALUES("abcdeheh11","呵呵11");
-
mapper映射文件
<!-- 指定类名 和 表名 -->
<class name="test03.Demo04" table="demo04">
<!-- 指定主键列对应的属性 -->
<id name="id" column="id" type="string">
<!--<generator class="identity"/>--><!-- 主键自增方式:数据库自增::auto_increment-->
<!--<generator class="increment"/>--><!--主键自增方式:hibernate自增-->
<!--name="table" 数据库中主键发生表-->
<!--name="column" 主键发生所在字段,必须初始化,即有一条记录设置了初始值-->
<!--name="max_lo" 高位连接数字-->
<!--hilo:高低位
<generator class="hilo">
<param name="table">demo03_hilo</param>
<param name="column">hilo_value</param>
<param name="max_lo">0</param>
</generator>
-->
<generator class="uuid"/>
</id>
<!--非主键对应的属性-->
<property name="name" column="name" />
</class>
-
启动类
//测试添加
System.out.println("添加一个:::"+session.save(new Demo04("1234","呵呵1234")));
System.out.println("添加一个:::"+session.save(new Demo04(null,"呵呵12345")));
-
日志信息
添加一个:::40284ccd8a645197018a6451999d0001
添加一个:::40284ccd8a645197018a645199bf0002
Hibernate: insert into demo04 (name, id) values (?, ?)
Hibernate: insert into demo04 (name, id) values (?, ?)
5.5 sequence:序列自增
sequence:序列自增 适用于支持序列的数据库 只能针对于数字类型的主键
-
项目引入oracle的驱动 ojdbc6.jar
-
oracle创建表和序列
CREATE TABLE demo05(
id int PRIMARY KEY,
NAME VARCHAR(100)
);
create sequence seq_demo05 start with 1000;
-
更改hibernate的核心配置文件::指定连接数据库的四大参数和方言
<?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>
<!-- 指定方言 -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl40</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.username">tian</property>
<property name="connection.password">123</property>
<!-- 是否显示sql语句 -->
<property name="show_sql">true</property>
<!-- 导入类与表的映射文件 -->
<mapping resource="test03/Demo05.hbm.xml" />
</session-factory>
</hibernate-configuration>
-
mapper映射文件
<!-- 指定类名 和 表名 -->
<class name="test03.Demo05" table="demo05">
<!-- 指定主键列对应的属性 -->
<id name="id" column="id" type="int">
<!--<generator class="identity"/>--><!-- 主键自增方式:数据库自增::auto_increment-->
<!--<generator class="increment"/>--><!--主键自增方式:hibernate自增-->
<!--name="table" 数据库中主键发生表-->
<!--name="column" 主键发生所在字段,必须初始化,即有一条记录设置了初始值-->
<!--name="max_lo" 高位连接数字-->
<!--hilo:高低位
<generator class="hilo">
<param name="table">demo03_hilo</param>
<param name="column">hilo_value</param>
<param name="max_lo">0</param>
</generator>
-->
<!--<generator class="uuid"/>-->
<generator class="sequence">
<param name="sequence">seq_demo05</param>
</generator>
</id>
<!--非主键对应的属性-->
<property name="name" column="name" />
</class>
-
启动类
//测试添加
System.out.println("添加一个:::"+session.save(new Demo05(1234,"呵呵1234")));
System.out.println("添加一个:::"+session.save(new Demo05(null,"呵呵12345")));
-
打印的日志信息
Hibernate: select seq_demo05.nextval from dual
添加一个:::1000
Hibernate: select seq_demo05.nextval from dual
添加一个:::1001
Hibernate: insert into demo05 (name, id) values (?, ?)
Hibernate: insert into demo05 (name, id) values (?, ?)
5.6 assigned:手动赋值
assigned:手动赋值 调用save前 对象的id必须手动赋值
-
sql
CREATE TABLE demo06(
id int PRIMARY KEY,
NAME VARCHAR(100)
);
-
mapper映射文件
<!-- 指定类名 和 表名 -->
<class name="test03.Demo06" table="demo06">
<!-- 指定主键列对应的属性 -->
<id name="id" column="id" type="int">
<!--<generator class="identity"/>--><!-- 主键自增方式:数据库自增::auto_increment-->
<!--<generator class="increment"/>--><!--主键自增方式:hibernate自增-->
<!--name="table" 数据库中主键发生表-->
<!--name="column" 主键发生所在字段,必须初始化,即有一条记录设置了初始值-->
<!--name="max_lo" 高位连接数字-->
<!--hilo:高低位
<generator class="hilo">
<param name="table">demo03_hilo</param>
<param name="column">hilo_value</param>
<param name="max_lo">0</param>
</generator>
-->
<!--<generator class="uuid"/>-->
<!--
<generator class="sequence">
<param name="sequence">seq_demo05</param>
</generator>
-->
<generator class="assigned"></generator>
</id>
<!--非主键对应的属性-->
<property name="name" column="name" />
</class>
-
启动类
System.out.println("添加一个:::"+session.save(new Demo06(1234,"呵呵1234")));
System.out.println("添加一个:::"+session.save(new Demo06(null,"呵呵12345")));
-
报错