1 概念
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库
概念解释
orm:object relational mapper 对象关系映射
持久层实现java类的属性与rdbms表的列一一对应关系
实现java对象和结果集行的对应关系
域模型:java中模型对象的思想
java类之间的关系
关联关系:订单和客户:订单要指定其所属客户 (部分依赖)
聚集关系:轮胎和车:轮胎是车的一部分 (整体和部分)
依赖关系:action和service:action中所有方法都要通过service来实现 (类似于寄生)
一般关系:儿子和父亲:继承关系
关系模型:rdbms中的二维表
:1对1 :把从表的主键定义为外键 来引用主表的主键
:n对n :定义一个关系表:定义两列作为联合主键 这两列作为外键 类分别引用另外两张表的主键
:1对n :把1定义为主表 把n定义为从表 在从表中定义一个外键来引用主表的主键
2 hibernate案例
2.1 创建项目:web/java
2.2 导入jar包
2.3 创建核心配置文件
- 位置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_37
hibernate.connection.username=root
hibernate.connection.password=root
hibernate.show_sql=true #是否显示sql语句
2.4 创建数据库
DROP TABLE student;
CREATE TABLE `student` (
`sid` INT(11) NOT NULL AUTO_INCREMENT,
`sname` VARCHAR(11) DEFAULT NULL,
`sex` CHAR(1) DEFAULT NULL,
`score` FLOAT(4,1) DEFAULT NULL,
`sdy` TINYINT(1) DEFAULT NULL,
`sbirthday` DATE DEFAULT NULL,
PRIMARY KEY (`sid`)
) ENGINE=INNODB AUTO_INCREMENT=221 DEFAULT CHARSET=utf8
INSERT INTO student VALUES(
NULL,
SUBSTRING(UUID(),1,8),
IF(RAND()>0.5,"男","女"),
CEIL(RAND()*100),
RAND()>0.5,
CONCAT(CEIL(RAND()*10+1990),"-",CEIL(RAND()*12),"-",CEIL(RAND()*31))
);
SELECT * FROM student;
2.5 mapper映射文件:
public class Student implements Serializable {
private Integer sid;
private String sname;
private String sex;
private Float score;
private Boolean sdy;
private Date sbirthday;
...
}
- 指定表的列与类的属性的对应关系:位置必须和实体类同一个包 名字必须是:实体类.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- 指定类名 和 表名 -->
<class name="sss.entity.Student" table="student">
<!-- 指定主键列对应的属性 -->
<id name="sid" column="sid" type="int">
<!-- 主键自增方式:数据库自增-->
<generator class="identity"/>
</id>
<property name="sname" column="sname" type="string"/>
<property name="sex" column="sex" type="string"/>
<property name="sbirthday" column="sbirthday" type="date"/>
<property name="sdy" column="sdy" type="boolean"/>
<property name="score" column="score" type="float"/>
</class>
</hibernate-mapping>
2.6 测试类
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Student;
import java.util.Date;
import java.util.List;
public class Test {
public static void main(String[] args) {
//1 创建Configration对象 自动读取heibernate的核心配置文件
Configuration conf = new Configuration();
//2 读取指定实体类的mapper映射文件
conf.addClass(Student.class);
//3 通过Configuration创建sessionfactory对象
SessionFactory factory = conf.buildSessionFactory();
//4 获取连接
Session session = factory.openSession();
//5 创建事务
Transaction transaction = session.beginTransaction();
//6 开启事务
transaction.begin();
/*通过session实现crud*/
//获取一个
Student s1 = (Student) session.get(Student.class, 221);
System.out.println(s1);
//获取所有
//hql语句:面向对象的
Query query = session.createQuery("from sss.entity.Student");
List<Student> list = query.list();
System.out.println(list);
//添加一个
session.save(new Student(1, "叶晨", "男", 66f, false, new Date()));
//修改一个:要求修改和删除之前必须先获取对象
Student s2 = (Student) session.get(Student.class, 222);
s2.setSbirthday(new Date());
s2.setScore(33f);
s2.setSname("楚灵");
s2.setSex("女");
session.update(s2);
//删除一个
Student s3 = (Student) session.get(Student.class, 223);
session.delete(s3);
//事务提交
transaction.commit();
//关闭连接
session.close();
}
}
3 hibernate改进(配置文件是xml)
3.1 创建xml核心配置文件:
- 名字随意
- 位置随意:hibernatepro.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>
<!-- 指定方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 指定连接的四大参数 -->
<property name="connection.url">jdbc:mysql://localhost:3306/ssr</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- 是否显示sql语句 -->
<property name="show_sql">true</property>
<!-- 导入类与表的映射文件 -->
<mapping resource="sss/entity/Student.hbm.xml"/>
</session-factory>
</hibernate-configuration>
3.2创建测试类
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Student;
public class TestPro {
public static void main(String[] args) {
//1 创建Configration对象 自动读取heibernate的核心配置文件
Configuration conf = new Configuration();
//2 读取核心配置文件
conf.configure("sss/test/hibernatepro.xml");
//3 通过Configuration创建sessionfactory对象
SessionFactory factory = conf.buildSessionFactory();
//4 获取连接
Session session = factory.openSession();
//5 创建事务
Transaction transaction = session.beginTransaction();
//6 开启事务
transaction.begin();
//增 删 改 ......
//7 事务提交
transaction.commit();
//8 关闭连接
session.close();
}
}
4 主键自增方式(策略)
- 在save插入行数据时 指定主键值的方式
- 在xml中修改
<id name="sid" column="sid" type="int">
<generator class="identity"/><!-- 主键自增方式:数据库自增-->
</id>
4.1 可选类型
* increment:适用于int/long/short类型的字段: hibernate自增
* identity:适用于int/long/short类型的字段:数据库自增:支持auto_increment的数据库:mysql
* sequence:通过sequence实现自增的数据库:oracle
* assinged:主键列由程序员手动赋值
* uuid:适用于string类型的字段:随机一个32位16进制的字符串
* hilo:适用于int/long/short类型的字段 根据高/低位算法自动生成
* native:由程序根据数据库自动选择:identity、sequence、hilo
4.2 increment自增
<id name="sid" column="sid" type="int">
<--主键自增方式:auto_increment [数据库需要使用auto_increment 否则无效]-->
<generator class="identity"/>
<!-- 主键自增方式:hibernate自增-->
<generator class="increment"/>
</id>
//添加一个
session.save(new Student("韩梅3","女",11f,true,new Date()));//不指定sid 通过hibernate自增 自动赋值
Hibernate: select max(sid) from student
Hibernate: insert into student (sname, sex, sbirthday, sdy, score, sid) values (?, ?, ?, ?, ?, ?)
increment自增是hibernate自增:会先查询当前表的主键的最大值 然后最大值+1给添加的对象的主键列赋值
不适应于:多线程或者分布式项目
4.3 sequence序列自增
CREATE TABLE stu(
sid INT PRIMARY KEY,
sname VARCHAR(20),
sex CHAR(3),
score FLOAT,
sbirthday DATE
)
CREATE sequence seq_stu_11 START WITH 1000
INSERT INTO stu VALUES(
seq_stu_11.nextval,
dbms_random.string('x',6),
'男',
trunc(dbms_random.value*100,1),
to_date(trunc(dbms_random.value*10+1990)||'-'||trunc(dbms_random.value*12+1)||'-'||trunc(dbms_random.value*30+1),'yyyy-MM-dd')
);
public class Stu implements Serializable {
private Integer sid;
private String sname;
private String sex;
private Float score;
private Date sbirthday;
...
}
- 创建mqpper映射文件-->Stu.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- 指定类名 和 表名 -->
<class name="sss.entity.Stu" table="stu">
<!-- 指定主键列对应的属性 -->
<id name="sid" column="sid" type="int">
<!--<generator class="identity"/> 主键自增方式:数据库自增 auto_increment-->
<!-- <generator class="increment"/>主键自增方式:hibernate自增-->
<!-- sequence自增 -->
<generator class="sequence">
<param name="sequence">seq_stu_11</param>
</generator>
</id>
<property name="sname" column="sname" type="string"/>
<property name="sex" column="sex" type="string"/>
<property name="score" column="score" type="float"/>
<property name="sbirthday" column="sbirthday" type="date"/>
</class>
</hibernate-mapping>
<?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:orcl</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.username">wen</property>
<property name="connection.password">123</property>
<!-- 是否显示sql语句 -->
<property name="show_sql">true</property>
<!-- 导入类与表的映射文件-->
<mapping resource="sss/entity/Stu.hbm.xml"/>
</session-factory>
</hibernate-configuration>
//添加一个
session.save(new Stu("楚灵", "女", 11f, new Date()));
4.4 uuid自增:只适用于字符串类型的主键列
CREATE TABLE tea(
tid varchar(50) primary key,
tname VARCHAR(20)
)
- mapper映射文件
- 注意:使用uuid定义id必须是String类型
<id name="sid" column="sid" type="int">
<!-- uuid自增-->
<generator class="uuid"/>
</id>
//插入一条数据
session.save(new Stu("楚宣", "女", 11f, new Date()));
5 表与表之间的关系
5.1 1对n
创建数据库
CREATE TABLE tea(
tid INT PRIMARY KEY AUTO_INCREMENT,
tname VARCHAR(11)
);
INSERT INTO tea VALUES(1,"李老师");
INSERT INTO tea VALUES(2,"郭老师");
CREATE TABLE stu(
sid INT PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR(11),
stid INT,
CONSTRAINT fk_099 FOREIGN KEY(stid) REFERENCES tea(tid)
);
INSERT INTO stu VALUES(1001,"李老师学生1",1);
INSERT INTO stu VALUES(1002,"李老师学生2",1);
INSERT INTO stu VALUES(2001,"郭老师学生1",2);
INSERT INTO stu VALUES(2002,"郭老师学生2",2);
创建实体类
public class Stu implements Serializable {
private Integer sid;
private String sname;
//定义引用记录老师
private Tea tea;
...
}
public class Tea implements Serializable {
private Integer tid;
private String tname;
//定义集合记录学生
private Set<Stu> stuSet;
...
}
mapper映射文件
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- 指定类名 和 表名 -->
<class name="sss.entity.Stu" table="stu">
<!-- 指定主键列对应的属性 -->
<id name="sid" column="sid" type="int">
<!-- 自增-->
<generator class="identity"/>
</id>
<property name="sname" column="sname" type="string"/>
<!--n对1-->
<!--
many-to-one:
name:n中定义的引用
column:外键列名
-->
<many-to-one name="tea" column="stid" class="sss.entity.Tea"/>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- 指定类名 和 表名 -->
<class name="sss.entity.Tea" table="tea">
<!-- 指定主键列对应的属性 -->
<id name="tid" column="tid" type="int">
<!-- 自增-->
<generator class="identity"/>
</id>
<property name="tname" column="tname" type="string"/>
<!--1对n-->
<!--
one-to-money:
set的属性:name 对应的n集合的引用名
key的column:从表的外键列名
one-to-money的class:集合元素的类型
-->
<set name="stuSet" lazy="true">
<key column="stid"/>
<one-to-many class="sss.entity.Stu"/>
</set>
</class>
</hibernate-mapping>
测试
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Stu;
public class TestPro {
public static void main(String[] args) {
//1 创建Configration对象 自动读取heibernate的核心配置文件
Configuration conf = new Configuration();
//2 读取核心配置文件
conf.configure("sss/test/hibernatepro.xml");
//3 通过Configuration创建sessionfactory对象
SessionFactory factory = conf.buildSessionFactory();
//4 获取连接
Session session = factory.openSession();
//5 创建事务
Transaction transaction = session.beginTransaction();
//6 开启事务
transaction.begin();
Stu s1 = (Stu) session.get(Stu.class, 1001);
System.out.println(s1);
//7 事务提交
transaction.commit();
//8 关闭连接
session.close();
}
}
5.2 1对1
创建数据库
CREATE TABLE husband(
hid INT PRIMARY KEY AUTO_INCREMENT,
hname VARCHAR(11)
);
INSERT INTO husband VALUES(1,"李先生");
INSERT INTO husband VALUES(2,"高先生");
CREATE TABLE wife(
wid INT PRIMARY KEY AUTO_INCREMENT,
wname VARCHAR(11),
CONSTRAINT fk_091 FOREIGN KEY(wid) REFERENCES husband(hid)
);
INSERT INTO wife VALUES(1,"李太太");
INSERT INTO wife VALUES(2,"高太太");
实体类
public class Husband implements Serializable {
private Integer hid;
private String hname;
//定义引用记录妻子
private Wife wife;
...
}
public class Wife implements Serializable {
private Integer wid;
private String wname;
private Husband husband;
...
}
mapper映射文件
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- 指定类名 和 表名 -->
<class name="sss.entity.Husband" table="husband">
<!-- 指定主键列对应的属性 -->
<id name="hid" column="hid" type="int">
<!-- 自增-->
<generator class="identity"/>
</id>
<property name="hname" column="hname" type="string"/>
<!--1对1-->
<one-to-one name="wife" class="sss.entity.Wife"/>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- 指定类名 和 表名 -->
<class name="sss.entity.Wife" table="wife">
<!-- 指定主键列对应的属性 -->
<id name="wid" column="wid" type="int">
<!-- 自增-->
<generator class="identity"/>
</id>
<property name="wname" column="wname" type="string"/>
<!--1对1-->
<one-to-one name="husband" class="sss.entity.Husband"/>
</class>
</hibernate-mapping>
<?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.MySQLDialect</property>
<property name="connection.url">jdbc:mysql://localhost:3306/ssr</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- 是否显示sql语句 -->
<property name="show_sql">true</property>
<!-- 导入类与表的映射文件-->
<mapping resource="sss/entity/Stu.hbm.xml"/>
<mapping resource="sss/entity/Tea.hbm.xml"/>
<mapping resource="sss/entity/Husband.hbm.xml"/>
<mapping resource="sss/entity/Wife.hbm.xml"/>
</session-factory>
</hibernate-configuration>
测试
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Husband;
import sss.entity.Wife;
public class TestPro {
public static void main(String[] args) {
//1 创建Configration对象 自动读取heibernate的核心配置文件
Configuration conf = new Configuration();
//2 读取核心配置文件
conf.configure("sss/test/hibernatepro.xml");
//3 通过Configuration创建sessionfactory对象
SessionFactory factory = conf.buildSessionFactory();
//4 获取连接
Session session = factory.openSession();
//5 创建事务
Transaction transaction = session.beginTransaction();
//6 开启事务
transaction.begin();
Husband h1 = (Husband) session.get(Husband.class, 1);
System.out.println(h1+":::"+h1.getWife());
Wife w1 = (Wife) session.get(Wife.class, 2);
System.out.println(w1+":::"+w1.getHusband());
//7 事务提交
transaction.commit();
//8 关闭连接
session.close();
}
}
5.3 n对n
创建表
CREATE TABLE tab_goods(
gid INT PRIMARY KEY AUTO_INCREMENT,
gname VARCHAR(11),
gprice FLOAT(6,1)
);
INSERT INTO tab_goods VALUE (1,"铅笔",2.1);
INSERT INTO tab_goods VALUE (2,"橡皮",0.5);
INSERT INTO tab_goods VALUE (3,"本子",1.0);
CREATE TABLE tab_order(
oid INT PRIMARY KEY AUTO_INCREMENT,
omoney FLOAT(9,1),
otime DATE
);
INSERT INTO tab_order VALUES(1,10000,'2021-01-01');
INSERT INTO tab_order VALUES(2,2000,'2021-02-01');
INSERT INTO tab_order VALUES(3,300,'2021-03-01');
CREATE TABLE tab_goods_order(
ooid INT,
ggid INT,
PRIMARY KEY(ooid,ggid),
CONSTRAINT fk_092 FOREIGN KEY(ooid) REFERENCES tab_order(oid),
CONSTRAINT fk_093 FOREIGN KEY(ggid) REFERENCES tab_goods(gid)
);
INSERT INTO tab_goods_order VALUES(1,1),(1,2),(1,3);
INSERT INTO tab_goods_order VALUES(2,1),(2,2);
INSERT INTO tab_goods_order VALUES(3,1),(3,3);
实体类
public class Goods implements Serializable {
private Integer gid;
private String gname;
private Float gprice;
private Set<Order> orderSet;
......
}
public class Order implements Serializable {
private Integer oid;
private Float omoney;
private Date otime;
private Set<Goods> goodsSet;
......
}
映射文件
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- 指定类名 和 表名 -->
<class name="sss.entity.Goods" table="tab_goods">
<!-- 指定主键列对应的属性 -->
<id name="gid" column="gid" type="int">
<!-- 自增-->
<generator class="identity"/>
</id>
<property name="gname" column="gname" type="string"/>
<property name="gprice" column="gprice" type="float"/>
<!--n对n-->
<set name="orderSet" table="tab_goods_order">
<!--key的column当前表tab_goods在关系表中的外键列-->
<key column="ggid"/>
<!--many-to-many的column对方表tab_order在关系表中的外键列-->
<many-to-many column="ooid" class="sss.entity.Order"/>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- 指定类名 和 表名 -->
<class name="sss.entity.Order" table="tab_order">
<!-- 指定主键列对应的属性 -->
<id name="oid" column="oid" type="int">
<!-- 自增-->
<generator class="identity"/>
</id>
<property name="omoney" column="omoney" type="float"/>
<property name="otime" column="otime" type="date"/>
<!--n对n-->
<set name="goodsSet" table="tab_goods_order">
<!--key的column当前表tab_order在关系表中的外键列-->
<key column="ooid"/>
<!--many-to-many的column对方表tab_goods在关系表中的外键列-->
<many-to-many column="ggid" class="sss.entity.Goods"/>
</set>
</class>
</hibernate-mapping>
<?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.MySQLDialect</property>
<property name="connection.url">jdbc:mysql://localhost:3306/ssr</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- 是否显示sql语句 -->
<property name="show_sql">true</property>
<!-- 导入类与表的映射文件-->
<mapping resource="sss/entity/Stu.hbm.xml"/>
<mapping resource="sss/entity/Tea.hbm.xml"/>
<mapping resource="sss/entity/Husband.hbm.xml"/>
<mapping resource="sss/entity/Wife.hbm.xml"/>
<mapping resource="sss/entity/Goods.hbm.xml"/>
<mapping resource="sss/entity/Order.hbm.xml"/>
</session-factory>
</hibernate-configuration>
测试
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Goods;
import sss.entity.Order;
public class TestPro {
public static void main(String[] args) {
//1 创建Configration对象 自动读取heibernate的核心配置文件
Configuration conf = new Configuration();
//2 读取核心配置文件
conf.configure("sss/test/hibernatepro.xml");
//3 通过Configuration创建sessionfactory对象
SessionFactory factory = conf.buildSessionFactory();
//4 获取连接
Session session = factory.openSession();
//5 创建事务
Transaction transaction = session.beginTransaction();
//6 开启事务
transaction.begin();
Goods g1 = (Goods) session.get(Goods.class, 2);
System.out.println(g1 + ":::" + g1.getOrderSet());
Order o1 = (Order) session.get(Order.class, 3);
System.out.println(o1 + ":::" + o1.getGoodsSet());
//7 事务提交
transaction.commit();
//8 关闭连接
session.close();
}
}
6 hibernate中get和load的区别
1 都是通过主键获取一个对象
2 都需要指定对象的类型
get和load的区别
1:当对应的主键值不存在时:
get返回的是null
load抛出异常:ObjectNotFoundException
2:正常运行时:
get会立刻发送并执行sql语句 获取对应的结果对象
load不会立刻发送sql语句 load方法获取的是proxy代理对象
(此对象类型和id确定但其他属性无值)
只有当调用代理对象时才发送和执行sql语句
如果session关闭才第一次调用代理对象会抛出异常:LazyInitializationException
7 属性lazy和cascade
懒加载:lazy="true" 默认:
学生关联老师:获取学生时 如果不调用老师
学生的老师属性tea赋值的是代理对象:只有id属性
只有在调用此老师属性时 才执行sql语句
如果session关闭 才第一次调用此老师属性会报错:LazyInitializationException
立刻加载:lazy="false" 默认:
学生关联老师:会执行两个sql语句:sql1获取学生 sql2获取学生关联的老师
cascade="save-update":级联操作:添加或者修改学生时 学生关联的老师也会级联添加/修改
cascade="delete":级联操作:删除学生时 学生关联的老师也会删除
cascade="all":=cascade="save-update"+cascade="delete"
Order o1 = new Order(10, 11111f, new Date());
Set<Goods> set = new HashSet<>();
//注意:级联添加时:关联对象不能设置id
set.add(new Goods(null, "袜子1", 11f));
set.add(new Goods(null, "袜子2", 12f));
set.add(new Goods(null, "袜子3", 13f));
o1.setGoodsSet(set);
session.save(o1);
/*
Hibernate: insert into tab_order (omoney, otime) values (?, ?)
Hibernate: insert into tab_goods (gname, gprice) values (?, ?)
Hibernate: insert into tab_goods (gname, gprice) values (?, ?)
Hibernate: insert into tab_goods (gname, gprice) values (?, ?)
Hibernate: insert into tab_goods_order (ooid, ggid) values (?, ?)
Hibernate: insert into tab_goods_order (ooid, ggid) values (?, ?)
Hibernate: insert into tab_goods_order (ooid, ggid) values (?, ?)
*/
session.delete(session.get(Goods.class,4));
/*
先查询出所有有关联的表,然后删除
Hibernate: delete from tab_goods_order where ggid=?
Hibernate: delete from tab_goods_order where ooid=?
Hibernate: delete from tab_goods_order where ggid=?
Hibernate: delete from tab_goods_order where ggid=?
Hibernate: delete from tab_goods where gid=?
Hibernate: delete from tab_goods where gid=?
Hibernate: delete from tab_order where oid=?
Hibernate: delete from tab_goods where gid=?
*/
8 hibernate的检索方式
8.1 ognl对象导航:通过对象a来获取关联的对象b
/*
检索方式:OGNL:通过Stu关联的tea属性来获取对象
Stu s1 = (Stu) session.get(Stu.class, 1001);
System.out.println(s1.getTea());
*/
8.2 OID检索方式:通过get/load方法由主键值获取对象
/*
检索方式:OID:通过get/load方法获取对象
Stu s2 = (Stu) session.get(Stu.class, 1001);
System.out.println(s2);
*/
8.3 HQL检索方式:通过Query接口获取对象
/*
检索方式:HQL :通过Query接口方式hql(类sql语句:面向对象的sql语句)语句
idea中 hql中涉及到属性名会编译报错 但不影响执行
*** 执行查找 ***
Query q1 = session.createQuery("from sss.entity.Stu where sname=?");
(q1=session.createQuery("from sss.entity.Stu");)
q1.setParameter(0,"李老师学生1");
System.out.println(q1.list());
*** 执行修改 ***
Query q2 = session.createQuery("update sss.entity.Stu set sname=?
where sid=?");
q2.setString(0,"依依").setInteger(1,1001);
System.out.println(q2.executeUpdate());
*** 执行删除 ***
Query q3 = session.createQuery("delete from sss.entity.Stu where sid=?");
q3.setInteger(0,1001);
System.out.println(q3.executeUpdate());
*/
8.4 QBC检索方式:通过Criteria接口获取对象
/*
检索方式:QBC:通过Criteria接口 实现完全面向对象方式访问数据库
参考:https://www.cnblogs.com/lukelook/p/9692429.html
*** 查询所有 ***
Criteria c1 = session.createCriteria(Stu.class);
System.out.println(c1.list());
*** 模糊查询 ***
Criterion s1 = Restrictions.eq("sname", "李老师的学生2");
Criterion s2 = Restrictions.like("sname", "%1%");
Criterion s3 = Restrictions.or(s1, s2);
c1.add(s3);
System.out.println(c1.list());
*** 分页 ***
c1.setFirstResult(0);//设置起始行的索引:索引从0开始
c1.setMaxResults(2);//设置每页记录数
System.out.println(c1.list());
(System.out.println(c1.setFirstResult(0).setMaxResults(2).list());)
*/
8.5本地SQL检索方式:通过手写sql查询数据库
/*
检索方式:本地SQL:通过SQLQuery接口 写sql对数据库进行增删改查
SQLQuery sql1 = session.createSQLQuery("select * from stu where sid>? and sname=?");
List<Object[]> list1 = sql1.setInteger(0, 2).setString(1, "郭老师学生1").list();
for (int i = 0; i <list1.size(); i++) {
for (int j = 0; j <list1.get(i).length ; j++) {
System.out.println(list1.get(i)[j]);
};
}
SQLQuery sql2 = session.createSQLQuery("select * from stu where sid>?
and sname=?").addEntity(Stu.class);
List<Stu> list2 = sql2.setInteger(0, 1).setString(1, "郭老师学生1").list();
for (int i = 0; i <list2.size() ; i++) {
System.out.println(list2.get(i));
}
*/
9 hibernate自动创建表
<property name="hibernate.hbm2ddl.auto">create-drop</property>
hibernate.hbm2ddl.auto:通过mapper映射文件自动创建或者修改表
hibernate.hbm2ddl.auto=create:如果表存在先删除表再创建,如果表不存在直接创建
hibernate.hbm2ddl.auto=create-drop:如果表存在先删除表再创建,如果表不存在直接创建
SessionFactory:关闭前会删除创建的表
hibernate.hbm2ddl.auto=udpate:如果表不存在直接创建,表存在使用已有的,列同理
常用:hibernate.hbm2ddl.auto=udpate
10 hibernate中对象的状态
/*
***对象状态***
1:瞬时态=游离态:Transient
通过new创建的对象:此对象和session的数据库中的行无关,
对对象进行操作不会影响数据库中的行记录
Student s1=new Student(1,"韩雪","女",66f,true,new Date());
2:持久态:Persistent
通过load/get/list/iterator/save/saveorupdate等方法获取的对象,
此对象和sesson数据库中的某行是对应关系
s1=(Student)session.get(Student.class.1);
在session关闭前/事务提交前:hibernate会自动判断持久态对象和对应的行数据是否一致
如果不一致:会自动执行update语句,根据持久态对象的属性值来更改对应的行数据
List<Student> list1 = session.createQuery("from sss.entity.Student").list();
for (Student s:list1) {
if(s.getSex().equals("女")){
s.setScore(s.getScore()+200);
System.out.println(1);
}
}
Iterator<Student> it = session.createQuery("from sss.entity.Student").iterate();
while(it.hasNext()){
Student next = it.next();
System.out.println(next);
}
System.out.println(it);
3:脱管态:Detached
当session关闭/清空/事务提交后
持久态的对象转换为脱管态:此对象和session数据库行脱离关联关系
Student s1=new Student("5","韩雪","女",66.6,true,new Date());
session.evict(s1);//s1转换为脱管态
session.clear();
s1.setSex("圣");
s1.setScore(100.0);
Iterator<Student> it = session.createQuery("from sss.entity.Student").iterate();
while(it.hasNext()){
Student s = it.next();
if(s.getSex().equals("女")){
s.setScore(s.getScore()+200);
}
}
System.out.println(it);
*/