书到用时方恨少,是非经过不知难!最近听了一位前辈的课程,随手整理了一份知识点,与大家分享,还望圈内前辈多多指点,本文中有哪些不足,不严谨之处,请在底下留言,我好更正,以免给下一位读者带来不便,感谢各位!!!
Hibernate
好处:操作数据库,可以以面向对象的方式来完成。不需要书写SQL
ORM:对象关系映射
- hibernate属于4级:完全面向对象操作数据库
- Mybatis属于2级
- dbutils属于1级
搭建
-
导包
- antlr-2.7.7.jar
- dom4j-1.6.1.jar
- geronimo-jta_1.1_spec-1.1.1.jar
- hibernate-commons-annotations-5.0.1.Final.jar
- hibernate-core-5.0.7.Final.jar
- hibernate-jpa-2.1-api-1.0.0.Final.jar
- jandex-2.0.0.Final.jar
- javassist-3.18.1-GA.jar
- jboss-logging-3.3.0.Final.jar
- mysql-connector-java-5.1.7-bin.jar
-
创建数据库,数据表
-
书写ORM元数据(对象与表额映射配置文件)
- 导入约束
- 实体
- ORM元数据
-
书写主配置文件
- 必选属性配置(5个与数据库的连接相关属性)
<property name="hibernate.connection.driver_class">driver</property>
<property name="hibernate.connection.url">url</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
- 可选属性配置(3个)
<!-- sql语句是否打印到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- sql语句格式化 -->
<property name="hibernate.format_sql">true</property>
create 每次框架运行都会创建新的表,以前表将会被覆盖,表数据会丢失。
create-drop 每次框架运行结束都会将所有表删除。
update 如果表已存在不会再生成新表,如果表有变动,自动更新表(不会删除任何数据)。
validate 数据库中的列与*hbm.xml列是否对应,不对应就抱错
<property name="hibernate.hbm2ddl.auto">update</property>
-
元数据引入配置
<mapping resource="*.hbm.xml" />
Hibernate API详解
-
Configuration
- 加载主配置
- 创建sessionFactory
-
SessionFactory
- 创建session对象
- 属于线程安全的对象
- 注意:在web项目中,只创建一个sessionFactory
-
Session
- 与数据库之间的连接
- 获得事务
- CRUD
-
Transaction:封装了事务的操作
实体规则
-
实体类创建的注意事项
- 持久化类提供无参构造器
- 提供对属性Get/Set方法
- 持久化类的属性,尽量使用包装类
- 持久化类需要提供oid,与数据库中的主键列对应
- 不要用final修饰class(hibernate使用cglib代理生成对象)
-
主键类型
- 自然主键(少见):表的业务类中,某业务列符合:1、必须有,2、不重复的特征,则该列可作为主键使用(身份证)
- 代理主键(常见)
-
主键生成策略
- 代理主键生成策略
identity:主键自增,由数据库来维护主键值,录入时不需要指定主键
increment:主键自增,由Hibernate来维护,每次插入前检索id最大值,+1作为新的主键值。(并发时不安全)
sequence:Oracle中主键生成策略
hilo:高低位算法,主键自增,由hibernate来维护。
native:hilo+sequence+identity 自动3选1策略
uuid:产生随机字符串,作为主键,*注意*:主键类型必须为String类型
- 自然主键生成策略
assigned:自然主键生成策略。hibernate不会管理主键,由开发人员自主管理
Hibernate中的对象状态
-
对象3种状态
-
瞬时状态:没有id,没有Session缓存中
-
持久化状态:有id,在Session缓存中
-
游离|托管状态:有id,没有在session缓存中
-
3种状态转换图
一级缓存
- 缓存:提高效率。hibernate中一级缓存也是为了提高操作数据库效率
- 提高查询效率
- 减少更改所执行的sql语句
hibernate中的事务
事务
- 事务特性
- A 原子性
- C 一致性 (数据总量不变)
- I 隔离性
- D 持久性
- 事务并发产生问题
- 脏读:读到最终未提交的数据
- 不可重复读:2次连续读取,由于数据一致性,2次读取数据不一致
- 幻|虚读:整表操作,在对其删除同时,增加一条数据
- 事务隔离级别
- 读未提交 123
- 读已提交 23
- 可重复读 3(mysql默认)
- 串行化 没有问题
在hibernate中指定隔离级别
<property name="hibernate.connection.isolation">4</property>
- 0001 1 读未提交
- 0010 2 读已提交
- 0100 4 可重复读
- 1000 8 串行化
在项目中如何管理事务
- 事务打开、业务执行、事务提交、回滚事务。
- Service层及DAO层使用到session保证是同一个session对象
- 注意1:通过getCurrentSession()获得的session对象,当事务提交时,session会自动关闭,不要手动调用close关闭。
- 注意2: 调用getCurrentSession方法必须配合主配置中的一段配置。
<property name="hibernate.current_session_context_class">thread</property>
多表关系
1:N
- 实体对象
1:使用集合
N:直接引用1的一方
- 关系型数据库
N:使用外键的引用1的一方的主键
- 映射文件
1:<set name="">
<key column="">
<one-to-many class="">
</set>
N:<many-to-one name="" column="" class="" />
- 操作:操作管理级属性
- cascade:级别操作,减少我们书写操作的代码。
none(默认) 不及联
save-update 级联保存
delete 级联删除
all 级联保存+级联删除 - inverse:反转关系维护
属于性能优化。关系两端都使用了关系,双发都会发送维护关系语句, 这样就发生了重复,我们可以使用inverse使一的一方放弃维护关系(在1:N中一方可以放弃维护关系)
true : 放弃 ,false(默认): 维护
N:N
- 实体对象
两方使用集合。
- 关系型数据库
使用中间表,至少两列,作为外键引用两张表的主键
- 映射文件
<set name="" table="中间表名">
<key column="别人引用我">
<many-to-many class="" column="我引用别人">
</set>
- 操作:操作管理级属性
-
cascade:级别保存
none(默认) 不及联
save-update 级联保存
delete 级联删除
all 级联保存+级联删除 -
inverse:反转关系维护,属于性能优化。关系两端都使用了关系,必须选择一方放弃维护关系,放弃维护关系由业务方向决定(录入员工,员工和角色的关系,就由员工来维护)
true 放弃
false(默认) 维护
查询
查询-HQL语法
基础语法
String hql3 = " from Student";
Query query = session.createQuery(hql3);
List list = query.list();
条件
String hql2 = " from Student order by cust_id desc ";
Query query = session.createQuery(hql2);
List list = query.list();
分页
String hql1 = " from Student ";
Query query = session.createQuery(hql1);
query.setFirstResult(2);
query.setMaxResults(2);
List list = query.list();
- 多表查询
内连接:将连接到的对象分别返回,放到数组中
String hql = " from Student s inner join s.linkMens ";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
内连接迫切连接:自行进行封装,返回值就是一个对象
String hql = " from Student s inner join fetch s.linkMens ";
Query query = session.createQuery(hql);
List<Student> list = query.list();
左外连接
String hql = " from Student s left join s.linkMens ";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
左外迫切连接
String hql = " from Student s left join fetch s.linkMens ";
Query query = session.createQuery(hql);
List<Student> list = query.list();
右外
右外迫切连接
查询-Criteria语法
- 离线查询:操作数据库分为Controller、Service、DAO三层,在Controller层就创建离线的Criteria对象,直到DAO层进行执行。
//Controller/Service层:
DetachedCriteria dc = DetachedCriteria.forClass(Student.class);
dc.add(Restrictions.idEq(6l));//拼装条件
//DAO层:----------------------------------------------------
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//----------------------------------------------------
Criteria c = dc.getExecutableCriteria(session);
List list = c.list();
- 语法
条件
Criteria c = session.createCriteria(Student.class);
c.add(Restrictions.idEq(2l));
List<Customer> list = c.list();
查询优化
- 类级别查询
- get方法:没有任何策略,调用即立即查询数据库加载数据。
- load方法(默认): 应用类级别的加载策略。
- 关联级别查询(集合策略,关联属性策略)
集合策略
lazy属性: 决定是否延迟加载
true(默认值): 延迟加载,懒加载
false: 立即加载
extra: 极其懒惰,只查询集合的size(count语句)
fetch属性: 决定加载策略.使用什么类型的sql语句加载集合数据
select(默认值): 单表查询加载
join: 使用多表查询加载集合
subselect:使用子查询加载集合
关联属性策略
fetch 决定加载的sql语句
select: 使用单表查询
join : 多表查询
lazy 决定加载时机
false: 立即加载
proxy: 由customer的类级别加载策略决定.
no-session问题解决: 扩大session的作用范围.