■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ Hibernate框架 ↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Hibernate框架;
为什么要有?
框架是为了简化开发人员的代码,
和提高开发人员的开发效率,
而在现时的项目中都是基于MVC三层架构的,
可是在dao层中的代码出现大量的冗余,
因为这些冗余代码基本只是对数据操作方式的不同,从而只有小部分代码不同而已。
是什么?
是一个应用于MVC三层开发架构中的dao层的框架,是由一群Java爱好者开发的。
作用;
可以简化MVC三层开发架构的dao层开发的代码,以及提高开发效率
特点;
1.基于ORM思想的一个框架
2.对dao层的代码封装的很深,从而使得效率有点低下。
3.对数据库是强事务的操作
◆ 4.底层对JDBC的代码封装
◆ 5.在一定的程度上是一个强主键的dao层框架,
因为Hibernate框架对数据操作都是按照id进行操作的。
◆◆◆建议;创建表的时候,必须要有id
6.是使用代理类对需要进行操作的数据类进代理模式的操作
7.是实现了JPA接口(标准)【JPA是SUN公司定义用于ORM思想框架对Java的实现标准】
◆◆◆注;Hibernate只有对单表进行操作的时候是一个轻量级的框架。
----------------------------↓↓↓↓↓↓↓↓↓ Hibernate框架 —— ORM思想 ↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
ORM思想;
是什么?
Object Relation Mappping 对象关系映射,是一个dao层框架的设计思想。
使用效果;
Java开发人员只是需要管理对象,间接的管理与数据之间的关系
好处;
1) 面向对象
2) 可以不写sql语句
3) 查询更加方便,因为直接返回对象
弊端;
1) 如果封装的越复杂,对ORM思想的封装越彻底则越慢
基于ORM思想框架;
DBUtils ---> 是一个简单的ORM思想的框架不纯粹。
Hibernate ---> 是一个相对复杂的ORM思想的框架,相对的纯粹。
MyBatis ---> 是一个一般的ORM思想的框架
TopLink ---> 是IBM的框架的
。。。。。。
速度(快)的比较;
DBUtils ---> MyBatis ---> Hibernate
----------------------------↓↓↓↓↓↓↓↓↓ Hibernate框架基本开发步骤 ↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
Hibernate开发步骤;
1.导包
必须要导入\lib\required文件夹中的所有jar包,
因为这个包的所有jar包都是Hibernate框架的必须包。
2.编写Hibernate启动配置文件 ---> 看 00_框架.txt ---> 现用框架设计的基本设计
必配;
A_ 配置连接数据库基本参数
B_ 配置数据库的运行环境
C_ 建数据库表
D_ 建立javaBean,和数据库的表映射的JavaBean
E_ 创建表-对象映射文件
i) 配置ORM映射 ---> Object Relation Mapping 对象关系映射
3. 编写对数据库进行操作的代码
i) 编写读取src下的hibernate.cfg.xml文件的对象
ii) 创建服务注册器对象
iii) 使用读取sec下的hibernate.cfg.xml文件类的,
方法创建会话工厂对象维护所有的映射文件
iiii) 使用会话工厂对象创建具体的会话对象
iiiii) 使用具体的会话对象对数据库的数据进行操作
◆◆◆◆◆◆记得开启事务,关闭事务,关闭连接
----------------------------↓↓↓↓↓↓↓↓↓ Hibernate框架基本开发实现 ↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
基本开发实现;
1.导包
antlr-2.7.7.jar 〓 ---> Hierbante辅助包
dom4j-1.6.1.jar 〓 ---> dom4J技术对xml文件解析包
hibernate-commons-annotations-4.0.5.Final.jar 〓 ---> Hibernate注解核心包
hibernate-core-4.3.8.Final.jar 〓 ---> Hibernate框架核心包
hibernate-jpa-2.1-api-1.0.0.Final.jar 〓 ---> JPA框架支持包,融合了JPA框架
jandex-1.1.0.Final.jar
〓 ---> Hibernate辅助包
javassist-3.18.1-GA.jar
〓 ---> 字节码辅助包
jboss-logging-3.1.3.GA.jar
〓 ---> 日志包
jboss-logging-annotations-1.2.0.Beta1.jar 〓 ---> 注解日志包
jboss-transaction-api_1.2_spec-1.0.0.Final.jar 〓 ---> 事务支持包
2.编写Hibernate框架启动配置文件
◆建议;先确定表,确定对象在编写配置文件
A_ 建立数据库表
B_ 创建对应的映射javaBean类
◆◆ C_ 编写类和数据库表的映射文件
a)引入Hibernate框架核心包下的映射dtd约束文件,位于Hibernate核心jar包下的org.hibernate
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
b) 根据dtd映射约束文件编写相应的代码
◆◆◆映射文件小结;
1.如果name的值和column的值相同则column可以省略不写
2.在使用
组件策略的时候是使用数据库或Hibernate框架维护,
那么则开发人员赋值可能无效,只会使用底层自动生成的值
◆◆ 3.映射的文件名建议是;javaBean映射类 + .hbm.xml命名,
◆◆◆ 并且一个javaBean映射类对应一个*.hbm.xml文件
◆ 4.在使用··维护主键策略的时候,
之前设置的主键的值必须要是符合这个底层维护的
5.在使用type属性的时候最好使用数据库的类型,
因为避免类型的变化和预想的类型不一样,如类型的大小等......
6.建议;javaBean映射类的属性和数据库的表的字段名相同,便于后期的维护。
7.建议;在当前javaBean映射类的包下创建映射文件
◆ 8.属性技巧;
name 是类属性或类
column 是表或字段
key 是表
◆◆◆重◆◆◆注;因为Hibernate框架的对数据库的数据进行操作基本都是通过表的主键,
◆◆◆所以在建立表的时候必须要赋予一个主键。
◆◆ D_编写Hibernate配置文件;
a) 引入Hierbante框架核心包下的dtd约束文件,位于Hibernate核心jar包下的org.hibernate
---> ▲▲▲注意;映射文件的dtd,文件名
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
b) 根据dtd配置约束文件编写相应的代码
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
xxx
xxx
org.hibernate.dialect.MySQL5InnoDBDialect
是设置如果没有表则创建,
并且只会创建一次,如果有了表则直接对这个表进行维护
create ---> 是使用每一次对数据库的数据进行操作的时候,
旧表都会删除,重新创建一张新的表。
-->
update
◆◆◆◆◆注;一般是要设置某一个文件的路径,那么则是使用 ( / )
如果是设置某一个类的路径则是 ( . )
◆◆ E.编写对应的类连接数据库,并且对数据库的数据进行操作
//1.调用Configuration的方法读取src下的hibernate.cfg.xml文件
Configuration config = new Configuration().configure();
//另;在3.0之前是直接使用Configuration的方法创建SessionFacotry对象
//
SessionFactory before = config.buildSessionFactory();
//2.创建服务注册器对象,这个是在3.0之后推出的 ---> 速度可能快一点
ServiceRegistry registry = new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build();
//3.使用Configuration的方法创建SessionFactory对象传入一个服务注册器对象
//作用;SessionFactory类是使用加载所有的javaBean映射类的映射文件的
SessionFactory factory = registry.buildSessionFactory(registry);
//4.使用SessionFactory类的方法获取到具体的Session对象
Session session = factory.openSession();
//5.因为Hibernate框架是一个强事务的框架,所以必须要开启事物
session.beginTransaction();
//6.使用Session类的方法对数据库的数据进行操作
Student stu = new Student("小明",16);
session.save(stu);
//7.提交事务
session.getTransaction().commit();
//8.关闭连接
session.close;
factory.close();
◆◆◆◆◆注意;必须要开启事务和提交事务,
否则如果对数据库的数据进行操作的话则会无效
映射文件的type属性;
type 是设置这个映射类属性对应的数据库类型
而这个设置的类型的值有三种,hibernate、数据库、Java_API
+------>
对象的常用类型值;
|
Java_API
hibernate
MySql
|
↓↓↓
↓↓↓
↓↓↓
|
文件;
|
java.util.String
string/text
varchar/text/longtext
|
Java.util.Byte[]【数组[]】 binary
blob/mediumblob/longblob
|
|
整数;
|
java.lang.Integer
integer
int
|
java.lang.Short
short
short
|
|
小数;
|
java.lang.Double
double
double
|
java.lang.Float
float
float
|
|
日期;
|
java.lang.Date
date
date/datetime/timpstamp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
————====|========———————=======〓〓〓 Hibernate框架对数据基本操作 〓〓〓======——————————=============———————————————————————————————————
|
|
|
Hibernate对数据基本操作;
|
为什么要有?
|
因为Hibernate框架是一个在MVC+三层开发模式的开发中是位于dao层的,
|
而dao层是对数据库的数据进行操作的。
|
|
所以Hibernate框架必须要可以对数据库的数据进行操作。
|
|
特点;
|
1.都是使用Session类的方法对数据库的数据进行操作
|
2.必须要开启事务,因为hibernate是强事务的
|
|
|
|
|
--------|------------------------------↓↓↓↓↓↓↓↓↓ 对数据进行添加操作 ↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
|
|
|
对数据添加操作;
|
1.创建表 ---> test
|
2.创建对应的javaBean映射类 ---> Student
|
3.编写类映射文件 ---> student.hbm.xml
|
4.编写hibernate配置文件 ---> hibernate.cfg.xml
|
|
5.编写对数据库数据操作的代码
|
|
//1.使用Configuration的方法读取src下的hibernate.cfg.xml文件,并且获取到Configuration对象
|
Configuration config = new Configuration().configure();
|
|
//2.创建一个服务注册器对象
|
//传入config.getProperties()方法的数据,
//使用hibernate.cfg.xml文件配置的连接数据库的参数
|
ServiceRegistry registry = new StandardServiceResgitryBuild().applySettings(config.getProperties()).build();
|
|
//3.使用Configuration的方法传入一个ServiceRegistry对象创建SessionFactory对象,维护所有的映射文件
|
SessionFactory factory = config.buildSessionFactory(resgitry);
|
|
//4.使用SessionFactory的方法获取到具体的Session对象
|
Session session = factory.openSession();
|
|
//5.因为hibenrate是一个强事务的框架,所以必须要开启事务
|
session.beginTransaction();
|
|
//6.使用Session类的方法对数据库的数据进行···保存···操作
|
|
a_ 方式一;使用save()方法进行保存数据,如果主键是手动的,那么则相同的主键则报错
|
Student s = new Student();
|
s.setName("小宝");
|
s.setAge(18);
|
|
session.save(s)
|
|
b_ 方式二;使用saveOrUpdate()方法保存数据,如果主键相同则不会报错会进行一个更改操作
|
session.saveOrUpdate();
|
|
//提交事务
|
session.getTransaction().commit();
|
|
//关闭连接
|
session.close();
|
session.close();
|
|
|
|
|
--------|------------------------------↓↓↓↓↓↓↓↓↓ 对数据进行查找操作 ↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
|
|
|
对数据查找操作;
|
1.创建表 ---> test
|
2.创建javaBean映射类 ---> Student
|
3.编写类映射文件 ---> student.hbm.xml
|
4.编写配置文件 ---> hibernate.cfg.xml
|
|
5. 编写对数据库数据进行操作代码
|
|
//1.使用Configuration的方法读取src下的hibernate.cfg.xml文件
|
Configuration config = new Configuration().configure();
|
|
//2.创建服务注册器对象
|
//传入config.getProperties()方法的数据,
//使用hibernate.cfg.xml文件配置的连接数据库的参数
|
ServiceRegistry registry = new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build();
|
|
//3.使用Configuration的方法传入一个服务注册器对象创建SessionFactory对象,用于维护所有的映射文件
|
SessionFactory factory = config.buildSessionFactory(registry);
|
|
//4.使用SessionFactory方法,创建一个具体的Session对象
|
Session session = factory.openSession();
|
|
//5.Hibernate是一个强事务的dao层框架所以要开启事物
|
session.beginTransaction();
|
|
//6.使用Session类的方法对数据库的数据进行···查找···操作
|
|
a_ 方式一;用get()方法,传入一个对应的javaBean映射类的类对象,
|
并且通过传入一个数据库的主键的值,因为主键是唯一。
|
---> 获取某一个具体数据
|
Student stu = (Student)session.get(Student.class,1);
|
|
b_ 方式二;用load()方法,传入对应javaBean映射类的类对象,
|
并且通过传入一个数据库的主键的值,因为主键是唯一。
|
load()和get()有区别↓↓↓立即加载vs延迟加载
|
|
Student stu = (Student)session.load(Student.class,1);
|
|
c_ 方式三;使用hibernate定义的对数据库操作的语句 ---> 获取所有的数据
|
|
Query query = session.createQuery("select s from Student s");
|
List list = query.list();
|
|
for(Student s : list){
|
sysout(s);
|
}
|
|
|
c_ 方式四;使用hibernate定义HQL语句的对数据库操作的语句,定义的是预定义的语句
|
|
Query query = session.createQuery("select s from Student s where id=?");
|
|
◆◆◆ //对于预定义语句的值,必须是从0开始的
|
query.setParameter(0,1);
|
|
Student s = (Student)query.uniqueResult();
|
|
d_ 方式五;使用hibernate定义的QBC语句的对数据查找的语句,也是有预定义的值的
|
|
Criteria criteria = session.createCriteria("select s from Student s where id=2");
|
//使用Restrictions的对应数据库的语句,存入对应的属性字段名,并且设置值
|
crriteria.add(Restrictions.eq("salary",6000));
|
List stu = critera.list();
|
for(Student s : list){
|
sysout(s);
|
}
|
|
//7.提交事务
|
session.getTransaction().commit();
|
|
//8.关闭连接
|
sesion.close();
|
factory.close();
|
|
|
◆◆◆具体查找语句看↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓Hibernate框架查询数据
|
|
◆◆◆注;查找数据,并没有对数据起到了操作的作用,
|
所有也可以不开启事务,但是开启事务符合标准规范。
|
|
◆◆◆注;在使用Hibernate定义的对数据库的数据进行查找的语句,
|
如果返回的是多个对象,则是使用list()方法,
|
如果是单个则使用uqueResult()方法。
|
|
--------|------------------------------↓↓↓↓↓↓↓↓↓ 对数据进行更新操作 ↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
|
|
|
对数据更新操作;
|
1.创建表 ---> test
|
2.创建对应的javaBean映射类对象 ---> Student
|
3.编写类映射文件 ---> student.hbm.xml
|
4.编写配置文件 ---> hibernate.cfg.xml
|
|
5.编写对数据库操作的代码
|
|
//1.使用Configuration的方法读取src文件下的hibernate.cfg.xml文件
|
Configuration config = new Configuration().configure();
|
|
//2.创建服务注册器对象,注册服务器连接
|
//传入config.getProperties()方法的数据,
//使用hibernate.cfg.xml文件配置的连接数据库的参数
|
ServiceRegistry registry = new StandardServiceRegisryBuilder().applySettings(config.getProperties()).build();
|
|
//3.使用Configuration的方法传入一个服务注册器对象创建SessionFactory对象,用于维护所有的映射文件
|
SessionFactory factory = config.build(registry);
|
|
//4.创建具体的Session对象
|
Session session = factory.openSession();
|
|
//5.因为Hibernate是一个强事务的框架,所以要开启事务
|
session.getTransaction();
|
|
//6.使用Session的方法对数据库的数据进行···更改···的操作
|
|
a_ 方式一;定义一个需要更改的对应的javaBean映射类,使用Session的方法进行操作
|
Student s = new Student();
|
s.setId(2);
|
s.setName("小明");
|
s.setAge(20);
|
|
session.update(s);
|
|
c_ 方法二;使用saveOrUpdate()方法,没有数据则保存,有数据则进行更改
|
session.saveOrUpdate(s);
|
|
b_ 方式二;使用查找出来的对象,对这个对象的数据进行更改并且提交
|
Student s = (Student) session.get(Student.class,2);
|
s.setName("小黑");
|
s.setAge(18);
|
|
|
|
//7.提交事务
|
session.getTransaction().commit();
|
|
//8.关闭连接
|
session.close();
|
session.close();
|
|
◆◆◆建议;使用先查找后修改的方式
|
|
|
|
|
|
--------|------------------------------↓↓↓↓↓↓↓↓↓ 对数据进行删除操作 ↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
|
|
|
对数据删除操作;
|
1.创建表 ---> test
|
2.创建对象的javaBean映射类 ---> Student
|
3.配置对象的类的映射文件 ---> student.hbm.xml
|
4.编写hibernate框架的配置文件 ---> hibernate.cfg.xml
|
|
5.编写对数据库数据进行操作的代码
|
|
//1.使用Configuration的方法读取src下的hibernate.cfg.xml文件
|
Configuration config = new Configuration().configure();
|
|
//2.创建服务注册器对象
|
//传入config.getProperties()方法的数据,
|
//使用hibernate.cfg.xml文件配置的连接数据库的参数
|
ServiceRegistry registry = new StandardServiceRehgistryBuilder().applySettings(config.getProperty).build();
|
|
//3.使用Configuration类的方法传入一个ServiceRegistry对象创建SessionFactory对象用于维护所有的的映射文件
|
SessionFactory factory = config.buildSessionFactory(registry);
|
|
//4.使用SessionFactory的方法创建具体的Session对象
|
Session session = config.openSession();
|
|
//5.因为Hibernate框架是一个强事务的dao层的框架,所以要开启事物
|
session.beginTransaction();
|
|
//6.使用Session的方法对数据库的数据进行···删除···操作
|
|
◆建议;先查找在删除,可以避免各种问题......
|
|
a_ 使用查找到的对象进行删除,因为查找到的对象包括了主键
|
Student s = session.get(Student.class,1);
|
session.delete(s);
|
|
b_ 自定义一个对象,因为Hibernate是根据主键进行删除的, ---> 不建议
|
所以只需要设置这个对象的主键的值就可以了。
|
Student s = new Student();
|
s.setId(5);
|
session.delete(s);
|
|
//提交事务
|
session.commit();
|
|
//关闭连接
|
session.close();
|
factory.close();
|
|
|
|
|
————————|—————————————————————————————————— Hibernate框架 —— 存储文件 —————————————————————————————————————————————————————————————————————
|
|
|
存储文件;
|
为什么要存储文件?
|
虽然数据库资源很宝贵,所以不建议存储数据,
|
但是有一些机密的数据需要存储到数据库中。
|
|
特点;必须要使用对应的类型进行操作
|
|
文件类型;
+----------------------> 二进制类型;↑↑↑↑↑↑↑↑↑↑↑↑看上类型↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ---> byte[]
+----------------------> 文本类型;↑↑↑↑↑↑↑↑↑↑↑↑↑看上类型↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ---> String
-------------------------↓↓↓↓↓↓↓↓↓ Hibernate框架 —— 存储文件实现代码 ↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件实现代码;
1.创建表 ---> test === 要有对应的文件类型的字段 <--|
2.创建javaBean映射类 ---> Student === 必须要有对应的文件类型的属性 <--|
3.编写类映射文件 ---> studen.cfg.xml
4.编写hibernate配置文件 ---> hibernate.cfg.xml
5.操作文件数据实现代码
//1.创建Configuration对象,使用这个类的方法读取src下的hibernate.cfg.xml文件
Configuration config = new Configuration().configure();
//2.创建ServiceRegistry对象
//传入config.getProperties()方法的数据,
//使用hibernate.cfg.xml文件配置的连接数据库的参数
ServiceRegistry registry = new StandardServiceResgiryBuilder().applySeyttings(config.getProperties()).build();
//3.使用Configuration的方法传入一个注册服务的对象用于创建SessionFactory对象,用于维护所有的映射文件
SessionFactory factory = config.buildSessionFactory(registry);
//4.使用会话工厂对象的方法创建具体的Session对象
Session session = factory.openSession();
//5.因为Hibernate是一个强事务的dao层框架,所以要开启事物
session.beginTransaction();
//6.使用session的方法对数据进行保存
———————=============———————=======〓〓〓 Hibernate框架数据映射 〓〓〓======——————————=============———————————————————————————————————
数据映射;
为什么要有?
在各种项目的数据存放到数据库中,
一个项目基本都会有几个表等,
但是这些表之间可能有关联,
那么在使用Hibernate对数据库的数据进行查找的时候,
怎么查找出关联的数据?
是什么?
是Hibernate定义的一个重要的功能。
作用;
用于查询数据库的表数据的时候,也查询到这个表的关联表的数据。
特点;
1.都是有关联关系的。
2.数据库最少有两张表
----------------------------------------- Hibernate框架数据映射分类 -----------------------------------------
数据映射分类;
类型分类;
基本属性映射;
Set集合
List集合
Map集合
◆注;普通的属性映射,使用集合的时候,
是按照使用的这个集合的特性进行使用的。
如;Set是无序的,那么存放则是无序的
对象映射;
一对多 ---> 单向
多对一 ---> 单向
一对多(多对一) ---> 单向
多对多 ---> 双向
一对一 ---> 双向/单向
——————————————————————————————————— Hibernate框架基本类型映射实现代码 ———————————————————————————————————————————————————————
------------------------------------------------ Set集合映射 -------------------------------------------------------
Set集合
特点;无序,在一次使用(存储到集合)的时候不可重复,
如果这个对象在集合中销毁了才可以重复
a_ 创建表 ---> student
b_ 创建对应的表的javaBean类 ---> Student
▲ 在编写这个类的时候需要指定集合成员变量,并且提供对应的get()和set()方法
Set address;
◆◆◆ 建议;加上泛型,可以控制数据的完整性和安全性
c_ 编写hibernate.cfg.xml文件
d_ 编写对应的类的映射文件
▲ 编写对应的集合成员变量的表映射
说明;
是用于配置对应javaBean映射类的Set集合成员变量
name 是这个成员变量位于这个javaBean的成员变量名
是设置这个副表和主表之间的外键
column 是这个副表的外键字段名,会自动使用主键的
是设置这个副表存放数据的字段,
因为在集合中是存放数据的,
而集合中的数据中就是存放到数据库的。
type 可以查看↑↑↑↑↑↑↑↑Hibernate框架基本开发实现,
映射文件的type属性。
column 是可以设置这个集合的数据存放的字段
◆◆◆注;这些属性是必须要配置的,缺一不可。
e_ 在操作类中编写代码
//1.创建Configuration类对象,并且使用这个类的方法读取src下的hibernate配置文件
Configuration config = new Configuration().config();
//2.创建注册服务器对象
//传入config.getProperties()方法的数据,
//使用hibernate.cfg.xml文件配置的连接数据库的参数
ServiceRegistry registry = new StandardServiceRegistry().applySettings(config.getProperties()).build();
//3.通过Configutaion的方法创建SessionFactory对象,
//
用于维护所有的映射文件以及二级缓存,并且传入一个ServiceRegistry的对象
SessionFactory factory = config,buildSessionFactory(registry);
//4.使用会话工厂的方法创建一个具体的Session对象
Session session = factory.openSession();
//5.因为Hibernate框架是一个强事务的框架,所以必须要开启事务
session.beginTransaction();
//6.设置数据
Set set = new Set();
set.add("广州中山大道西");
Student stu = new Student();
stu.setAddress(set);
//7.提交事务
session.getTransaction().commit();
//8.关闭连接
session.close();
factory.close();
---------------------------------------------- List集合映射 -------------------------------------------------------
List集合;
特点;有序,存储到集合的数据是可以重复的。
a_ 创建表 ---> student
b_ 创建对应的javaBean映射类对象 ---> Student
▲ 在Student映射类中需要创建这个List集合类型的成员变量,
并且必须要提供get()和set()方法。
List address;
◆◆◆ 建议;加上泛型,可以控制数据的完整性和安全性
c_ 编写对应的javaBean类的映射文件
▲ 编写javaBean类的List集合成员变量的映射
说明;
是定义这个映射类中的List集合的属性的数据映射
name 是这个List集合在映射类中的成员变量名
是设置当前这个类位于这个集合对应的数据库表(副表)的外键
column 是这个外键的字段名
因为List集合是一个有序的,
而如果是使用主键(id)可能出现不符合有序(小到大)特点
如;删除了id=2的数据,那么则可能出现一个空行
column 是这个序号的值字段名
是这个集合数据的存储的字段
type 可以查看↑↑↑↑↑↑↑↑Hibernate框架基本开发实现,
映射文件的type属性。
column 是指定这个字段的值
d_ 编写hibernate配置文件
e_ 编写操作数据的代码
//1.创建Configuration对象读取src下的hibernate.cfg.xml
Configuration config = new Configuration().configure();
//2.创建注册服务器对象,
//传入config.getProperties()方法的数据,
//使用hibernate.cfg.xml文件配置的连接数据库的参数
ServiceRegistry registry = new StandardServiceRegistry().applySettings(config.getProperties()).build();
//3.通过Configuration的方法传入服务注册的对象创建会话工厂对象,用于维护所有的映射文件和二级缓存。
SessionFactory factory = config.buildSessionFactory();
//4.通过会话工厂对象创建具体的会话
Session session = factory.buildSession();
//5.因为Hibernate框架是一个强事务的框架,所以要开启事物
session.beginTransaction();
//6.操作数据
List list = new List();
list.add("上海体育路");
Student student = new Student();
student.setList(list);
session.save(student);
//7.提交事务
session.getTransaction().commit();
//关闭连接
session.close();
factory.close();
------------------------------------------------ Map集合映射 -------------------------------------------------------
Map集合;
特点;保存在Map集合的数据,key是不可重复的,并且Map是无序的,但在映射中...... --->+
|
+<----------------------------------------------------------------------------------------+
|
|
a_ 创建表 ---> student
|
b_ 创建表对应的javaBean映射类 ---> Student
|
|
▲ 在这个映射类中要创建一个Map集合类型的成员变量,并且提供get()和set()方法
|
|
Map cargo;
|
|
c_ 编写javaBean类的映射文件
|
|
▲ 编写javaBean映射类的Map成员变量的映射
|
|
|
|
|
|
|
|
说明;
|
是定义这个映射类中的Map类型的成员变量的
|
name 是这个成员变量位于这个映射类中的成员变量名
|
|
是当前这个映射类位于这个Map副表的外键,自动使用主表的主键值
|
column 是这个外键的字段名
|
|
因为map的key的是用于唯一标识当前这个类的Map属性的key
+---------------------------------------->
如果在存储的时候,Map集合的数据出现key重复则使用后定义的。
type 可以查看↑↑↑↑↑↑↑↑Hibernate框架基本开发实现,
映射文件的type属性。
column 是指定这个字段的名字
是这个Map集合的value对应的字段
type 可以查看↑↑↑↑↑↑↑↑Hibernate框架基本开发实现,
映射文件的type属性。
column 是指定这个字段的名字
d_ 编写hibernate配置文件
e_ 编写操作数据代码
//1.创建Configuration对象读取src下的hibernate.cfg.xml
Configuration config = new Configuration().configure();
//2.创建注册服务器对象,
//传入config.getProperties()方法的数据,
//使用hibernate.cfg.xml文件配置的连接数据库的参数
ServiceRegistry registry = new StandardServiceRegistry().applySettings(config.getProperties()).build();
//3.通过Configuration的方法传入服务注册的对象创建会话工厂对象,用于维护所有的映射文件和二级缓存。
SessionFactory factory = config.buildSessionFactory();
//4.通过会话工厂对象创建具体的会话
Session session = factory.buildSession();
//5.因为Hibernate框架是一个强事务的框架,所以要开启事物
session.beginTransaction();
//6.操作数据
Map map = new HashMap();
map.add("上海体育路");
Student student = new Student();
student.setList(map);
session.save(student);
//7.提交事务
session.getTransaction().commit();
//关闭连接
session.close();
factory.close();
———————————————————————————————————————————————— 自定义工具类 ——————————————————————————————————————————————————————————
自定义工具类;
因为Hibernate框架定义的对数据进行操作的代码太多是冗余了,所以可以考虑抽象为一个工具类
class HibernateUtils{
private static SessionFafactory factory = null;
//获取具体的会话对象
public static Session getSession(){
//1.创建Configuration对象读取src下的hibernate.cfg.xml
Configuration config = new Configuration().configure();
//2.创建注册服务器对象,
//传入config.getProperties()方法的数据,
//使用hibernate.cfg.xml文件配置的连接数据库的参数
ServiceRegistry registry = new StandardServiceRegistry().applySettings(config.getProperties()).build();
//3.通过Configuration的方法传入服务注册的对象创建会话工厂对象,用于维护所有的映射文件和二级缓存。
SessionFactory factory = config.buildSessionFactory();
//4.通过会话工厂对象创建具体的会话
Session session = factory.buildSession();
//5.返回具体的会话对象
return session;
}
//关闭连接
public static void closeConnect(Session session){
if(session != null){
session.close();
}
if(factory != null){
factory.close();
}
}
}
———————————————————————————————————— Hibernate框架对象映射实现代码 ———————————————————————————————————————————————————————
◆◆◆◆◆◆技巧;1.在做对象映射的时候必须要先确定关系,那个是一方,那个是多方,
因为一方是用集合作为多方的成员变量,多方直接用一方的对象作为成员变量。
2.确定外键是在哪一方(表/类)
3.确定主表和副表
------------------------------------------------- 一对多映射 单向 -------------------------------------------------------
一对多映射;客人=订单
1.确定关系;
Customers 是一方 ---> 主表
Orders 是多方 ---> 副表
2.外键位于Orders
a_ 创建表 ---> customers(客户)、orders(订单)
b_ 创建对应的javaBean对象 ---> Customers、Orders
Customers
Orders
id
id
name
number
Set
▲ 在Customers类中先定义一个集合,
类型为Orders的成员变量,
提供get()和set()方法。
private Set orders = new HashSet(); ---> 为了简化操作时的代码
get()......
set()......
c_ 编写javaBean类映射文件
在orders映射文件中,按照正常映射书写
▲ 在Customers映射文件中,加上
说明;
是设置成员变量中的Set集合的数据
name 是这个set集合位于Customers(一方)类中的成员变量名
cascade 是设置这两个关联的表的级联
save-update ---> 添加和修改的级联
delete ---> 删除级联
all ---> 包含上面所有
+<-----
inverse 是设置这个外键的维护权反转给别的表
|
false ---> 默认
|
true ---> 交给别的类维护外键值
|
|
这个是为了提高效率的。
|
|-------->
如;在做添加的时候,
hibernate的insert into .....语句中的外键是没有值,
而后面在使用update语句给这个外键赋值的。
◆◆◆◆◆注;默认的维护权在一方
是设置当前这个Customers类位于的Orders(多方表)的外键字段
column 是外键字段名
是指定这个外键位于的表对应的javaBean映射类的类路径
class 是指定这个映射类的类路径
d_ 编写hibernate映射文件
e_ 编写操作数据代码
//1.使用 ↑↑↑ HiberteneUtils类的方法获取具体的会话对象
Session session = HibernateUtils.getSession();
//2.因为Hibernate是强事务的,所以要开启事务
session.beginTransaction();
//3.操作数据
Orders order = new Orders();
order.setNumber("a201611");
Customers customer = new Customers();
customer.setName("小明");
customer.getOrders().add(order);
//4.提交事务
session.getTransaction().commit();
//5.使用 ↑↑↑ HiberteneUtils类的方法关闭连接
HibernateUtils.closeConnet(session);
------------------------------------------------- 多对一映射 单向 -------------------------------------------------------
多对一映射;客人=订单
1.确定关系;
1.Customers ---> 一方
2.Orders ---> 多方
2.外键位于Orders
3.确定主副表;
1.Customers ---> 主表
2.Orders ---> 副表
a_ 创建表 ---> customers(主表)、orders(副表)
b_ 创建对应的javaBean映射类
Customers
Orders
id
id
name
number
Customers customer
▲ 在Orders类中创建Customers类类型的成员变量
private Customers customer;
c_ 编写映射文件
▲ Customers则按照正常的规则进行编写
▲ Orders则按照正常规则编写,在编写一个映射
column="c_id"
class="com.xx.Customers"
cascade="all">
说明;
是设置这个副表和主键直接的关系
name 是Customers(主表)这个类位于Orders类的成员变量名
column 是设置这个Customers映射类的表,
位于Orders映射类的表的外键字段名。
class 是这个外键的级联的类的类路径
cascade 是设置这两个表之间的级联范围
save-update 保存/修改级联
delete
删除级联
all
所有
◆◆◆注;因为在多对一中是由副表(外键表)来进行操作的
d_ 编写hibernate.cfg.xml配置文件
e_ 编写操作代码
//1.使用 ↑↑↑ HiberteneUtils类的方法获取具体的会话对象
Session session = HibernateUtils.getSession();
//2.因为Hibernate是一个强事务的框架,所以要开启事务
session.beginTransaction();
//3.操作代码
Customers customer = new Costomers();
customer.setName("夏洛莱");
Orders order = new Orders();
order.setNumber("201611");
order.setCustomers(customer);
//4.提交事务
session.getTransaction().commit();
//5.使用 ↑↑↑ HiberteneUtils类的方法关闭连接
HibernateUtils.closeConnect(session);
--------------------------------------------- 一对多(多对一)映射 双向 -------------------------------------------------------
一对多(多对一)映射;客人=订单
---> 就是一对多和多对一单向合并就是双向了,但是要注意外键维护权。
1.确定关系;
Customers ---> 一方
Orders ---> 多方
2.外键位于Orders
3.确定主表和副表;
1.Customers ---> 主表
2.Orders ---> 副表
a_ 创建表 ---> customers(主表)、orders(副表)
b_ 创建对应的javaBean映射类
Customers
Orders
id
id
name
number
Set orders
Customers customer
▲ 在Costomer类中创建对应的Orders类类型的集合(Set)的成员变量,
并且提供对应的get()和set()方法。
private Set orders = new HashSet(); ---> 为了节约代码
get()......
set()......
▲ 在Orders类中创建对应的Customers类的成员变量,
并且提供对应的get()和set()方法。
private Customers customer;
c_ 编写对应的javaBean映射类的映射文件
▲ 编写Customers映射类的映射文件,
其余的属性正常编写。
说明;
是设置javaBean类的这个集合数据和副表的映射
name 是这个Set集合成员变量名
cascade 是设置关联表之间的级联
save-update ---> 保存/修改级联
delete ---> 删除级联
all ---> 包含所有
inverse 是设置这个外键的维护权, ---> 默认是false
因为如果是一对多双向的情况下,
建议;最好把外键给副表维护。
因为主表的对应类添加数据的时候,
Hibernate发送第一条的sql语句是,
没有加上外键值的之后会在使用,
update进行修改的,这样降低了效率.
也避免出现不可预知性的错误
是定义这个Cutomers(主表)位于Orders(副表)的外键
column 是这个外键字段名
是设置这个映射的类型,
这个Orders(副表)对应的类路径。
▲ 编写Orders映射类的文件,
其余属性正常规则编写。
column="c_id"
class="com.xx.Customers"
cascade="all">
说明;
是设置映射类(表)和关联表的关联
name 是这个关联表对应的映射类位于当前这个类的成员变量名
column 是这个设置外键字段名
class 是设置这个对应的关联类的类路径
cascade 是设置与关联类直接的级联
save-update ---> 保存/更改级联
delete ---> 删除级联
all ---> 包含所有
◆◆◆◆◆注;双方的外键的字段名必须要是同一个。。。。。。
d_ 编写hibernate.cfg.xml配置文件
e_ 编写操作代码
//1.使用 ↑↑↑ HiberteneUtils类的方法获取具体的会话对象
Session sesion = HibernateUtils.getSession();
//2.因为Hibernate是强事务的,所以要开启事务
session.beginTransaction();
//3.操作数据
Orders orderT = new Orders();
order.setNumber("201611");
Customers customer = new Customers();
customer.setName("西华海");
cutomer.getOrders().add(customer);
Orders order = new Orders();
order.setNumber("201612");
order.getorders().add(customer);
session.save(order);
//4.提交事务
session.getTransaction().commit();
//5.使用 ↑↑↑ HiberteneUtils类的方法关闭连接
HibernateUtils.closeConnet(session);
---------------------------------------------- 多对多映射 双向 -------------------------------------------------------
多对多映射;老师 = 学生
1.确定位置;
Student 多方
Teacher 多方
2.使用一个中间表的字段作为外键,
但是外键不可以重复所以这个2个外键都设置为主键,
因为在多对多映射中都是多方,并且都是主表。
3.确定主副表;
Student 主表
Teacher 主表
a_ 创建表 ---> student、teacher
b_ 创建对应的javaBean类
Student
Teacher
id
id
name
name
Set teacher
Set student
▲ 在Student映射类中创建对应的集合成员变量,类型为关联类的类型
Set teacher = new HashSet(); ---> 节省操作代码
▲ 在Teacher映射类中创建对应的集合成员变量,类型为关联类的类型
Set student = new HashSet(); ---> 节省操作代码
c_ 编写映射类的映射文件
▲ 编写Student映射类的映射文件, ---> Student让出外键维护权
其余的属性按照正常规则编写。
说明;
是配置中间表(关联表)的数据
name 是这个javaBean映射类对应的表的关联表对应的javaBean类
table 是中间表名,因为多对多映射是使用一个中间表进行关联的
cascade 是设置两个实体表,之间的级联
save-update ---> 保存/修改级联
delete ---> 删除
all ---> 所有
inverse 是设置这个外键维护权的权利,默认是一方维护, ---> false默认
但是在多对多中的类都是多方,那么则必须要设置维护权。
这个key是当前这个映射类位于中间表
的主外键值
column 当前这个类的主外键的字段名
是设置这个当前映射类的关联类(表)
class 是这个关联类的类路径
column 是这个关联类(表)位于中间表的主外键字段
▲ 编写Teacher映射类的映射文件,
其余的属性按照正常规则配置。
说明;
是设置这个类(表)的关联映射类(表)
name 是这个关联类位于当前类的成员变量的变量名
table 这个中间表的表名,因为多对多映射是依靠中间表进行管理
cascade 是当前这个映射类对应的表和关联表的级联
save-update ---> 保存/修改级联
delete ---> 删除级联
all ---> 包括所有
◆◆注;因为Student映射类以及反转出主外键的控制权了
是当前这个映射类位于中间表的主外键字段名
column 是当前的映射类主外键字段名
是设置这个关联类的映射
class 是这个关联类的路径
column 是这个关联类位于中间表的主外键字段名
◆◆◆◆◆注;hibernate框架会自动将其设置为主外键
◆◆◆◆◆注;因为多对多中的类都是多方,并且双方都是主表,
所以必须要有一方让出外键(主键)维护权。
这个外键必须要设置成为一个主键,或者是唯一的,
否则数据结构会遭到破坏,使得业务需要被破坏。
d_ 编写hibernate.cfg.xml配置文件
e_ 数据操作的代码
//1.使用 ↑↑↑ HiberteneUtils类的方法获取具体的会话对象
Session session = HibernateUtils.getSession();
//2.因为Hibernate框架是一个强事务的框架,所以必须要开启事务
session.beginTreansaction();
//3.数据操作
Student stu1 = new Student();
stu.setName("小白");
Teacher tea1 = new Teacher();
tea1.setName("郑老师");
tea1.getStudent().add(stu1);
Student stu2 = new Student();
stu2.setName("黄老师");
stu2.getTeacher().add(tea1);
session.save(stu2);
//4.提交事务
session.getTransaction().commit();
//5.使用 ↑↑↑ HiberteneUtils类的方法关闭连接
HibernateUtils.closeConnect(session);
---------------------------------------------- 一对一映射 双向 -------------------------------------------------------
一对一映射; --- 外键字段必须是唯一的
1.确定关系;
Person ---> 一方
IdCard ---> 一方
2.外键位于idcard
3.确定主副表;
person ---> 主表
idcard ---> 副表
a_ 创建表 person、idcard
b_ 创建对应的映射类
Person
IdCard
id
id
name
number
IdCard idCard
Person person
▲ 编写Person映射类的映射文件,
其余属性都是按照正常规则编写。
class="com.xx.IdCard"
cascade="all">
说明;
是设置这个类(表)对应的关联类(表)
name 是这个关联类位于当前类的成员变量
class 是这个关联类的类路径
cascade 设置当前类(表)和关联类(表)的级联
save-update ---> 保存/修改级联
delete ---> 删除级联
all ---> 包括所有级联
▲ 编写IdCard映射类的映射文件,
其余属性按照正常规则编写。
方式一;外键 - 特殊的多对一
column="p_id"
class="com.xx.Person"
cascade="all"
unique=true>
说明;
在一对一中这是一个特殊的多对一配置从而配置为一对一的映射
name 是这个关联类位于当前类的成员变量名
column 是这个关联类位于当前类(表)的外键字段名
class 是这个关联类的类路径
cascade 当前这个映射类(表)与关联类的级联
save-update ---> 保存/修改级联
delete ---> 删除级联
all ---> 是所有
unique 是设置当前这个关联类的外键字段的值是唯一的
方式二;主键
class="com.xx.Person"
cascade="all"
constrained="true">
说明;
是设置当前这个映射类和关联类直接的关系
name 是设置这个关联类位于当前类的成员变量名
cascade 是当前类(表)和关联类(表)之间的级联
save-update ---> 保存/修改级联
delete ---> 删除级联
all ---> 所有级联
class 是这个关联类的类路径
constrained 是设置主键字段也做为外键,默认是false
———————=============———————=======〓〓〓 Hibernate框架查询数据 〓〓〓======——————————=============———————————————————————————————————
Hibernate查询数据;
为什么要有?
因为Hibernate框架是用于MVC三层开发模式的dao层,
而在实际的项目中基本都是对数据进行查找的为多,
所以Hibernate也为了适应不同的人群提供了···数种···查找方式。
是什么?
是Hibernate框架定义的查找数据库的功能。
作用;
用于查找数据库的数据。
特点;
1.hibernate都提供了对象封装的方法或内部封装
2.多个数据都是用list()方法
3.单个数据查找都是用uniqueResult()方法
4.都是可以使用预定义语句
------------------------------------ Hibernate框架对象查找方式分类 ------------------------------------------------------
Hibernate查找数据方式分类;
1.HQL ---> Hiberante Query Langurage
是Hibernate框架定义的查找数据库数据的语句,
是一个不纯粹的面向对象查找。
会将查找到的数据封装为对应的类的对象。
2.QBC ---> Query By Criteria 标准的查找
是Hibernate框架定义的查找数据库的语句,
是一个存储的面向对象查找。
3.原生SQL
是使用sql语言对数据库的数据进行查找
区别;
SQL
HQL
QBC
问题
兼容性
问题不大 使用不直观,较为复杂 --->+
速度 快 一般 慢
|
封装 没有封装
封装为对应映射类 封装复杂
|
使用 追求处理效率
对速率没要求 不推荐使用,不便于排错 <--+
类 SQLQuery Query Criteria、Restrictions
◆◆◆◆◆◆注;建议如果是不确定数据库会查出几条数据,
那么则建议尽量list()方法查询。
——————————————————————————————————————— Hibernate框架查询Utils —————————————————————————————————————————————
查询Uitls;
class QueryUtils{
//单个List遍历
public staitc void ergodicList(List list){
for(T t : list){
sysout(t);
}
}
//数组List遍历
public static void ergodicArr(List list){
for(Obejct[] object :list){
for(Object o : object){
sysout(o);
}
}
}
}
——————————————————————————————————————— Hibernate框架 —— HQL —————————————————————————————————————————————
HQL查询;◆◆◆如果是查询全表的数据则可以省略【select 对象(e)】
单表查询;
全表查询;
//1.定义查找语句,方式一
// A_ Query query = session.createQuery("select e from Employee e");
//方式二
B_ Query query = session.createQuery("from Employee e");
//2.使用list()方法获取到所有查询到的数据
List list = query.list();
//3.使用 ↑↑↑ QueryUtils的单个List遍历方法进行遍历
QueryUtils.ergodicList(list);
部分字段;
//1.定义查找语句;方式一
Query query = session.createQuery("select e.name,e.salary from Employee e");
//2.使用list()方法获取到所有查询到的数据,多个数据不同字段则返回的一个集合数组
List list = query.list();
//3.使用 ↑↑↑ QueryUtils的数组List方法进行遍历
QueryUtils.ergodicArr(list);
//方式二;必须要提供一个查找的属性个数对应的构造器
Query query = session.createQuery("new Employee(e.name,e.salary) from Employee e");
//使用list()方法获取到所有查询到的数据,多个数据返回一个集合
List list = query.list();
//使用 ↑↑↑ QueryUtils的ergodicList方法进行遍历
QueryUtils.ergodicList(list);
条件查询;> < <= >= <> = between-and and or like_% is-not-null is-null
一、查询某一个员工
//1.定义查询预定义语句
Query query = session.createQuery("from Employee where id=?");
//2.给预定义的位赋值
query.setParameter("2");
//3.因为是确定查询一个数据,因为主键是唯一的,
//
所以可以使用uniqueResult()方法获取到这个数据
Employee emp = (Employee)query.uniqueResult();
sysout(emp);
二、查询所有性别为null或为''空字符串的
//1.定义查询语句
Query query = session.createQuery("select e from Employee e where e.gender<>'' or e.gender is null ");
//2.因为不确定是会查出几个数据,所以使用list()方法
List list = query.list();
//3.使用↑↑↑ QueryUtils的ergodicList方法进行遍历
HibernateUtils.ergodicList(list);
三、查询工资在6000 - 8000和名字的包含第二个字包含天的,名字只有三个字
//1.定义查询语句
Query query = session.crateQuery("select e from Employee e where e.salary between 6000 and 8000 and e.name like %天_");
//2.因为不确定查询出几个数据,所以使用list()方法
List list = query.list();
//3.使用↑↑↑ QueryUtils的ergodicList方法进行遍历
HibernateUtils.ergodicList(list);
聚合查询;min max count sum
一、查询所有普通员工的工资总和
//1.定义查询语句
Query query = session.createQuery("select sum(e.salary) from Employee e");
//2.因为返回的是一个值,所以使用uniqueResult()获取方便,而sum对应的是long类型
Long salary = (Long)query.uniqueResult();
sysout(salary);
二、查询有多少个普通员工
//1.定义查询语句
Query query = session.createQuery("select count(e.id) from Employee e");
//2.因为返回的是一个值,所以使用uniqueResult()获取方便,而count对应的是int
Integer emp = query.uniqueResult();
sysout(emp);
分页查询;limit,但是Hql语句封装为对象了,所以使用特定的方法
//1.定义查询语句
Query query = session.createQuery("select e from Employee e");
//2.使用方法定义分页的值
query.setFirstResult(0); // 起始行
query.setMaxResult(5); //查询的行数
//3.使用list()方法获取到查询到的所有数据
List list = query.list()
//4.使用↑↑↑ QueryUtils的ergodicList方法进行遍历
QueryUtils.ergodicList(list);
分组查询;group by
//1.定义查询语句
Query query = session.createQuery("select e.gender,count(e.gender) from Emoloyee e where e.gender<>'' or e.gender is not null group by count(e.gender)");
//2.因为查询的是2个字段,而这个2个字段在对象的类中是没有2个都有的对应的成员变量
List list = query.list();
//3.使用↑↑↑ QueryUtils的ergodicList方法进行遍历使用
QueryUtils.ergodicList(list);
◆◆◆注;查找语句都是使用对象进行查找的,所以要注意大小写。
多表查询;
条件;
1.最少要有两个表的对应的映射类
2.数据库最少要有两个和映射类对应的表
◆ 3.多个表之间必须要有关联关系
一对多(多对一)
多对多
。。。。。。
■ 模拟数据,员工和部门
内连接查询;查询所有员工对应的部门
//1.定义查询语句
Query query = session.createQuery("select e.name,e.depart.departName from Employee e inner join e.depart");
//2.获取到查询的数据
List list = query.list();
//3.使用↑↑↑ QueryUtils的ergodicArr方法进行遍历集合数组数据
QueryUtils.ergodicArr(list);
右外连接查询;查询所有部门对应的员工信息
//1.定义查询语句
Query query = session.createQuery("select d from Department d right outer join Employee");
//2.获取到查询的数据
List list = query.list();
//3.遍历这个集合数组集合
for(Object [] object: list){
for(Object o : object){
if(o.getClass().getName().equalsIgonoreCase("list")){
for(object li : o){
sysout(li);
}
}else{
sysout(o);
}
}
}
左外连接查询;查询所有员工对应的上司
//1.定义查询语句
Query query = session.createQuery("select e.name,e.depart.princinal from Employee left outer join e.depart");
//2.使用list()方法获取所有的查询到的数据
List list = query.list();
//3.使用↑↑↑ QueryUtils的ergodicList方法进行遍历集合数组数据
QueryUtils.ergodicList(list);
可能出现的错;
1.注意两个类之间的toString方法,
不要互相调用,因为可能会出现死循环。
2.注意如果是只是获取一个表的数据,
那么在获取数据的时候不要toString,
对应的关联类的数据。
3.如果出现了Proxy代理类异常,
那么则重新导入所有的jar包,
以及删除MyEclipse自带的jar包
————————————————————————————————————— Hibernate框架 —— QBC —————————————————————————————————————————————
QBC查询;是纯面向对象的查询语句
单表查询;
单条件查询;
//1.定义查询语句
Criteria criteria = session.createCriteria(Employee.class);
//2.使用Restrictions的抽象方法进行查找,
//
而这个类的对应方法内部已经是定义了查找语句,
//
在使用Criteria的add()方法将这个定义好的Restrictions类的方法添加进去
criteria.add(Restrictions.eq("salary",6000));
//3.根据查询到的数据个数使用对应的方法获取 ---> list()
List list = criteria.list();
//4.使用↑↑↑ QueryUtils的ergodicList方法进行遍历集合数组数据
QueryUtils.ergodicList(list);
多条件查询;
//1.定义查询语句
Criteria criteria = session.createCriteria(Employee.class);
//2.使用Restrictions的抽象方法进行查找,
//
因为是多条件查询并且是and所以使用对应的静态方法
//
而在这个静态方法内部在添加对应的Restrictions的值
//
在使用Criteria的add()方法将这个定义好的Restrictions的静态方法添加进去
criteria.add(Restrictions.and(Restrictions.eq("salary",6000),Restrictions.eq("salary",8000)));
//3.根据查询到的数据使用对应的方法获取 ---> list()
List list = criteria.list();
//4.使用↑↑↑ QueryUtils的ergodicList方法进行遍历集合数组数据
QueryUtils.ergodicList(list);
常用的Restrictions的方法;
eq() ---> 等于
gt() ---> 大于
lt() ---> 小于
and() ---> 并且,多条件查询
between() ---> 并且...包括
allEq() ---> 所有相等
isNotNull() ---> 不为空
。。。。。。
————————————————————————————————————— Hibernate框架 —— SQL —————————————————————————————————————————————
SQL查询;
单表查询;
全表查询;
//1.定义所有查询的语句
SQLQuery sql = session.createQuery("select * from employee");
//2.添加需要进行封装的对象
sql.addEntity(Employee.class);
//3.使用对应的方法获取到对应的数据
List list = sql.list();
//4.使用↑↑↑ QueryUtils的ergodicList方法进行遍历集合数组数据
QueryUtils.ergodicList(list);
◆◆◆注;其余都是一样的。。。。。。
———————=============————————=======〓〓〓 Hibernate框架优化 〓〓〓======——————————=============———————————————————————————————————
Hibernate优化;
为什么要有?
Hibernate是一个纯粹的ORM(对象关系映射)思想的框架,
而这个框架对代码的封装太复杂了,使得效率的降低,
于是Hibernate框架使用了很多的方式去优化这个框架。
是什么?
是Hibernate框架自带,或者是第三方提供的插件优化(二级缓存)。
作用;
提高Hibernate的执行效率。
特点;
1.都是为了提高Hibernate的执行效率
◆ 2.都是通过减少数据库的访问次数
-------------------------------------------- 常用的Hibernate优化功能 ---------------------------------------------------
常用的优化功能;
一级缓存
对象状态定义 ---> 类似辅助一级缓存和二级缓存
立即加载VS延迟加载(懒加载)
二级缓存
-------------------------------------------- 一级缓存和二级缓存的区别 ---------------------------------------------------
一级和二级区别;
一级缓存;
Hibernate框架的一级缓存也称为Session缓存,
因为数据是存放到Session对象中的。
而Session对象一旦销毁,
那么存放到这个对象里的数据也会销毁。
所以数据是不可以跨Session的。
二级缓存;
Hibernate框架的二级缓存称为SessionFactory级别的缓存,
因为数据是存储到SessionFactory对象。
而只有SessionFactory销毁,
那么存放在这个对象里的数据才会销毁。
因为Session是从SessionFactory中获取的,
所以SessionFactory的数据是可以跨Session的。
区别;
一级缓存
二级缓存
+---------------+---------------------+---------------------------+
|
默认
|
开启
|
关闭
|
|
可关
|
不可以关
|
可以关闭和开启
|
|
会话
|
不可跨Session
|
可跨Session
|
|
内部数据 |
可操作 ---> 方法 |
不可操作 ---> 方法
|
|
查找顺序 |
先
|
后
|
+---------------+-------------------------------------------------+
————————————————————————————————————— Hibernate框架 —— 一级缓存 ——————————————————————————————————————————————————————————
-------------------------------------------- 一级缓存的现象 ------------------------------------------------------
一级缓存现象;
class Test(){
main(){
//1.通过自定义的HierbanteUilts获取到Session对象
Session session = HibernateUtils.getSession();
//2.因为Hibernate是一个强事务的框架,所以必须要开启事务
session.beginTransaction();
//3.操作数据
a_ 获取id为2的员工数据
Employee emp1 = (Employee) session.get(Employee.calss,2);
b_ 获取到相同id为2的员工数据
Employee emp2 = (Employee) session.get(Employee.class,2)
+---------------->
■■■■■■ 现象;
|
Hibernate框架只是会发送一条SQL语句到数据库,
|
而不会发送两条sql语句到数据库。
|
|
|
c_ 使用Session的方法对存储在Session对象中的缓存数据进行操作
|
|
session.flush(); ---> 与数据库的数据进行同步,
|
而这个方法在执行commit()方法的时候就会自动执行
|
|
session.evict(); ---> 删除某一个位于缓存的类对象,
|
|
session.clear(); ---> 清空所有缓存的数据
|
|
|
|
//4.提交事务
|
session.getTransaction.commit();
|
|
//5.使用自定义的HibernatUtils关闭连接
|
HibernateUtils.closeConnect(session);
|
|
}
|
|
}
|
|
+<-------- ■■■■■■ 解释;因为在每次在操作和数据库相关的数据的时候,
都会先到Hibernate一级缓存查找 ---->+
|
+<--------------------------------------------------------------------+
|
+-----------> 有;则直接在缓存中返回,则不会和数据库进行任何的交互
|
+-----------> 没;则会先到数据库查找,到了对应的数据则先保存到缓存中(Session),再返回给用户
操作缓存数据方法用途;
session.flush(); ---> 在rollback后使用
■■ 个人建议;不要在每一次操作数据库数据的时候都使用,
因为在提交时候的时候就已经执行了flush()方法,
并且是在提交事务之前执行这个方法的。
那么再次使用则降低了效率,虽然数据库及时的更新了。
假如;开发人员执行了flush()方法后,
而在commit()的时候不会在执行flush(),
也是不建议使用,因为将数据更新到了数据库,
如果在flush()出现异常那么则会导致数据的破坏,丢失......。
◆◆ 建议;在出现异常的时以及rollback后,
在进行flush(),避免有人恶意的利用漏洞恶意操作。
session.evict(); ---> 在出现两个不同的数据方向传入Session缓存中主键一样
例如;在查找数据库数据做判断后,
再次添加这个相同id的数据。
session.clear(); ---> 确定是一次性使用的Session或者,
是确定在很长的一段时间中不会再次使用。
例如;登录,用户登录后退出了一段时间,
后再执行clear()方法,
是为了避免用户在短时间再次登录,
从而造成更大的资源开销。
————————————————————————————————————— Hibernate框架 —— 对象状态 ——————————————————————————————————————————————————————————
对象状态;
为什么要有?
因为Hibernate框架封装的过于复杂,
那么Hibernate开发者则设计出各种用于提升Hibernate执行效率的办法。
而这些办法的根本就是减少和数据库的交互
而↑↑↑↑↑↑已经有几种减少和数据库的交互的办法,
◆◆◆ 但是怎么标识什么时候应该和数据库不进行交互?
是什么?
是Hibernate框架用于提高执行效率的一个功能(辅助功能)。
作用;
因为Hiberante是基于ORM思想(对象关系映射),
所以是面向对象的,而对象状态概念是用于定义需要查找的数据的类对象,
◆◆◆◆◆◆位于Hibernate框架中的状态。
特点;
1.都是用于提高Hibernate执行效率
2.都是在Session开启事务才会符合Hibernate框架定义的状态
------------------------------------- Hibernate框架 —— 对象状态分类 --------------------------------------------------------------
对象状态分类;
临时状态;
就是在使用Session对象开启事务之后,new 出来的对象都是一个临时状态的。
特点;
a_ 在数据库中没有对应的记录 ---> 没有使用这个对象和数据库进行过交互
b_ 没有OID ---> 因为Hibernate框架是根据主键进行查找的
c_ 在一级缓存中没有这个对象对应的数据
持久状态;
就是在使用Session对象开启事务之后,
使用new 出来的对象对数据库的数据进行操作,
而操作的时候也是有这个对象对应的数据。
特点;
a_ 在数据库有对应的记录 ---> 因为和数据库进行过交互,
而交互的时候也有这个数据。
b_ 有OID ---> 因为Hibernate框架是根据主键进行查找的,
而因为在数据库中有这个数据那么对象才有对应的id。
c_ 在一级缓存中有这个对象对应的数据,看 ↑↑↑↑↑↑ 一级缓存的现象
d_ 操作的对象和数据库的数据是有对应的数据的
如何进入持久状态;
load()、get()、upload()、createQuery()。。。。。。
◆◆◆ 只要是和数据库的数据进行交互,
并且交互之后数据库的数据的主键是没有发生改变的。
游离状态;
就是在使用Session开启事务之后,
将这个数据从缓存从删除。
特点;
a_ 在数据库有对应的记录 ---> 和数据库进行过对应的数据交互,
并且这个交互是在数据库中有数据库的。
b_ 有OID ---> 因为和数据库进行过数据交互,并且有对应的记录。
c_ 在一级缓存中是没有对应的数据 ---> 因为已经从缓存中删除了。
如何进入游离状态;
evict()、clear()......
◆注;使用update()、save()......方法可以从游离状态到持久状态
删除状态;
就是在使用Session开启事务之后,
将这个数据从数据库中删除。
特点;
a_ 在数据库中没有对应的记录 ---> 因为和数据库进行过对应的数据交互,
但是这个交互是在数据库中删除这个对应的数据。
b_ 有OID ---> 因为和数据库进行过交互,并且有对应的记录
c_ 在一级缓存中没有对应的记录 ---> 因为在从数据库删除的时候commit()方法,
就已经进行了同步了(flush)数据库的数据了。
———————————————————————————————————— Hibernate框架 —— 立即加载VS延迟加载 ——————————————————————————————————————————————————————————
立即VS延迟加载;
为什么要有?
因为可能在获取到了数据库的对应的对象的数据的时候,
可能就不需要立即使用(获取之后下一句代码出现异常)。
是什么?
是Hibernate框架定义的一个用于提高效率的功能。
作用;
是用于减少与数据库的交互次数的。
特点;
1.都是对数据库的数据进行操作
2.延迟加载默认是在映射文件开启的
--------------------------------------- 立即加载VS延迟加载 —— 代码实现 --------------------------------------------------------------
代码实现;
class Test{
main(){
//1.使用自定义的HibernateUtils类获取到Session对象
Session session = HibernateUtils.getSession();
//2.因为Hibernate框架是强事务的框架
session.beginTransaction();
//3.操作数据 -- 模拟
+-----立即加载-------> a_ 立即加载
|
Student stu = (Student)session.get(Student.class,2); ———> 立即加载
|
+-----延迟加载-------> b_ 延迟加载
|
Student stu = (Student)session.load(Student.class,3); ———> 延迟加载
+------getId()------->
sysout(stu.getId());
+------getName()----->
sysout(stu.getName());
|
|
|
//4.提交事务
|
session.getTransaction().commit();
|
|
//5.使用自定义HibernateUtils类关闭连接
|
HibernateUtils.close(session);
|
|
}
|
}
|
|
|
+--------------->
A_ 立即加载; --->get()
1.会立即执行sql语句,
查询数据库的数据。
2.取id执行查询数据库。
3.数据库找不到返回null。
4.无法转换成为延迟加载
B_ 延迟加载; ---> load()
1.不会立即执行sql语句
2.取id也不会查询数据库
3.只有在获取这个对应的对象的其他的成员变量的值,
的时候才会查询数据库。
所以如果只用id值对数据进行查找操作建议用load()
4.找不到则返回代理类对象,包含 $$
5.可以转换为立即加载
◆◆◆注;如果把映射文件的对应的标签的lazy属性设置为false,
那么延迟加载则会变成立即加载。
------------------------------------------- 延迟加载 —— 映射文件 --------------------------------------------------------------
配置文件;
在配置文件中的lazy属性是默认true,
-◆-
而这个lazy表中是在表和配置映射的标签中的lazy也是默认为true。
所以在使用对应的表的映射类的时候,
在查找关联表的时候是延迟查找的。
因为lazy默认是true
————————————————————————————————————— Hibernate框架 —— 二级缓存 ——————————————————————————————————————————————————————————
二级缓存;
为什么要有?
因为一级缓存无法跨Session,
而且Session那么在对一个数据库的数据进行操作完了之后关闭了这个Session,
那么在后续的相同对这个对象操作的都会重新加载缓存等。。。。。。
是什么?
是Hibernate框架提供的一个接口,用于提高执行的效率.
作用;
解决Session一级缓存的弊端,
提高执行的效率。
特点;
1.占用内存大 ---> 牺牲效率,提高性能
2.默认是开启的
3.需要引用第三方的插件,因为Hibernate框架只是提供了一个接口
◆◆◆注;只要Hibernate官网支持的第三方插件都可以。
------------------------------------------- 二级缓存 —— 实现代码 --------------------------------------------------------------
实现代码;
1.导入第三方插件包 ---> + hibernate-release-4.3.8.Final\lib\required
|--->
这个是Hibernate框架的jar包自带的。。。。。。
2.编写配置文件;
其余的正常编写。
加入;
true
org.hibernate.cache.ehcache.EhCacheRegionFactory
3.模拟二级缓存;
//1.使用自定义HibernateUtils工具类的方法获取到Session对象
Session session = HibernateUtils.getSession();
//2.因为Hibernate框架是一个强事务的框架,所以要开启事务
session.beginTransaction();
//3.模拟数据
Student stu = (Studnet)session.get(Student.class,1);
//清空一级缓存
session.clear();
//再次查找相同的映射类的数据。
// 〓 观察是否有发送查询语句到数据库,
//
如果有发那么则二级缓存没有生效,没有发则二级缓存生效了。
Student stu = (Student)session.get(Student.class,1);
//4.提交事务
session.getTransaction().commit();
//5.使用自定义的HibernateUtils工具类的方法关闭连接
HibernateUtils.close(session);
————————————————————————————————————————— 一级缓存和二级缓存的执行过程 ——————————————————————————————————————————————————————————
执行过程;
查找;
用户 ---> 一级缓存 ---> 二级缓存 ---> 数据库
找不到;则会抛出一个异常,并且不会在缓存中有这个对象的数据。
找到;
数据库 ---> 二级缓存 ---> 一级缓存 ---> 用户