Hibernate
# Hibernate
Hibernate 将 Java对象与数据库表之间建立起映射关系,并提供了一系列数据访问接口,可随心所欲对库进行操作
好处:
- Dao层开发简单
- 兼容性好支持大多数主流数据库
- 有二级缓存机制
- 省略手动编写SQL语句(自动生成
Hibernate 开发包: Hibernate 官网 (opens new window)
目录说明:
- documentation:开发文档
- lib:依赖jar包
- project:工程实例
学习参考文档:
- https://www.w3cschool.cn/hibernate/skzl1idz.html (opens new window)
- http://c.biancheng.net/hibernate/ (opens new window)
# ORM
ORM 是 Object Relational Mapping 的缩写,译为“对象关系映射”,它解决了对象和关系型数据库之间的数据交互问题
库与对象的关系
数据库 | 类对象 |
---|---|
表 | 类 |
表记录(数据) | 对象 |
表字段 | 对象属性 |
ORM缺点
- 学习成本高
- 自动生成SQL会消耗资源
- 复杂的SQL难以处理(有时候不如手写SQL
好处上面有了(总之是JDBC使用的优化版
# Hibernate架构
# 配置对象
用于 连接数据库 / 创建类和表映射关系 的主要 配置文件
默认全局配置文件:hibernate.cfg.xml
# 会话工厂对象
SessionFactory
对象 用于 分配线程的应用(安全线程),以防异步错乱的情况
# 会话对象
Session
对象 用于与数据库的物理连接
详细说明:https://www.w3cschool.cn (opens new window)
# 事务对象
Transaction
对象 每个事务代表 一个单元CRUD操作 (一个以上
# 查询对象
org.hibernate.Query
对象 用于 自定义SQL / Hibernate语句 查询的数据集
对象获取
==Session.createQuery(String hql);==
常用方法(结果集获取
返回 | 方法 | 说明 |
---|---|---|
R | uniqueResult() | 查询结果的单条数据,没有则null |
List<R> | list() | 查询结果集以list形式的结果 |
Iterator<R> | iterate() | 查询结果集以迭代器形式的结果 |
注意:list()方法 返回的数据 如果不为 实体对象的属性,那么它返回的是
Object[]
数组
# 约束对象
Criteria
对象 指定查询对象
# 配置属性
属性 | 说明 |
---|---|
hibernate.dialect | 配选定指定 库 生成对应的SQL |
hibernate.connection.driver_class | 加载 JDBC驱动 |
hibernate.connection.url | 连接库的url |
hibernate.connection.username | 用户名 |
hibernate.connection.password | 密码 |
hibernate.connection.pool_size | 连接池中连接的数量 |
hibernate.connection.autocommit | 允许JDBC自动提交模式 |
mapping
标签
- resource 指定的是需要已经配置好的 ORM映射xml文件
- class 指定实体对象(用于注解)
示例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/test</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root123</property>
<mapping resource="Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
# 映射文件
映射文件 主要用于 让配置文件对应对接的映射配置,但也与实体类对接
命名规则: ==<实体类名>.hbm.xml==
标签描述:
<hibernate-mapping>
:根元素的 XML 文件<class>
:指定 实体类 -> 数据库表 的特定映射name
:实体类(全限定名table
:数据库表名称
<id>
:类属性ID / 表ID字段 关联(唯一!!)name
:类属性名column
:表字段名type
:映射类型<generator>
自动生成主键值class
:主键自增形式generator.class值 说明 identity 库底层自增机制 increment Hibernate实现自增 assigned 字符串主键(算法生成 sequence 序列生成主键
<property>
:实体类属性 与 库表字段的匹配name
:类属性名column
:表字段名type
:映射类型
映射的数据类型:https://www.w3cschool.cn/hibernate/fzum1iem.html
示例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<meta attribute="class-description">
This class contains the employee detail.
</meta>
<id name="id" type="int" column="id">
<generator class="identity"/>
</id>
<property name="firstName" column="first_name" type="string"/>
<property name="lastName" column="last_name" type="string"/>
<property name="salary" column="salary" type="int"/>
</class>
</hibernate-mapping>
# Hibernate应用
Hibernate上机操作应用
# 搭建环境 IDEA
搭建步骤:
- 引入lib
- 连接数据库
- 项目结构 -> 模块 -> 选中项目 ->添加 Hibernate框架 (手动添加/生成 框架需要指定全局配置配置文件)
# 连接操作
应用前提:
- 已经包含有 实体类/数据库数据 ,且他们的 实体类属性/数据库表字段 数据类型一致
- ORM映射关系和全局配置已经完善
连接步骤:
读取解析 全局配置文件
==Configuration config = new Configuration().configure();==
读取解析映射信息,创建SessionFactiory
==SessionFactory sf = conf.buildSessionFactory();==
获取Session ==Session session = sf.openSession();==
启动事务
==Transaction tx = session.beginTransaction();==
CRUD操作数据 (通过session进行操作
提交事务
关闭资源
应用工具类
注意:由于新版使用的是 服务注册的形式 进行应用的,因此步骤可能有不一样
package com.sans.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class HibernateUtil {
private static ServiceRegistry sr;
private static SessionFactory sf;
private static ThreadLocal<Session> localThread = new ThreadLocal<>();
static {
Configuration config = new Configuration().configure();
sr = new ServiceRegistryBuilder().applySettings(
config.getProperties()).buildServiceRegistry();
config.buildSessionFactory(sr);
sf = config.buildSessionFactory(sr);
}
/**
* 获取会话
*/
public static Session getSession() {
Session session = localThread.get();
if (session == null || ! session.isOpen()) {
session = sf.openSession();
localThread.set(session);
}
return session;
}
/**
* 关闭会话
*/
public static void close() {
Session session = localThread.get();
if (session != null) {
session.close();
localThread.remove();
sf.close();
}
}
}
# 注解
Hibernate注解 是摆脱了 xml 配置文件的应用
应用前提:
- Hibernate 3.x 以上的注释包
- 关系jar包:
- annotations.jar
- hibernate-comons-annotations.jar
- ejb3-persistence.jar
注释 | 范围 | 参数 | 说明 |
---|---|---|---|
@Entity | 类 | - | 标志位实体类 bean |
@Table | 类 | String name 表名称 String catalog 目录 String schema 模式 UniqueConstraint[] uniqueConstraints 约束 | 映射表的配置 |
@Id | 属性 | - | 主键 |
@GeneratedValue | 属性 | GenerationType strategy 策略 String generator | 主键自动生成策略(一般默认即可) |
@Column | 属性 | String name 允许唯一 int length 指定数据长度 boolean nullable 非空 boolean unique 唯一 | 定义属性与字段的细节属性 |
示例:
SQL:
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
实体对象:
import javax.persistence.*;
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@Id @GeneratedValue
@Column(name = "id")
private int id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "salary")
private int salary;
public Employee() {}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
# 反向工程
反向工程操作原意 数据库表 -> 实体类
IDEA反向工程步骤:
**前提:**项目已 引入Hibernate框架
- 双击Shift -> 操作项搜索
Persistence
- 选中项目右键 ->
生成持久映射
- 指定数据库映射即可
添加 数据构架的映射关系 添加关系映射关系一般用于 ==一对一 / 一对多 / 多对多== 的情况应用
确认必要信息
源/目标 特定名称 (指定实体对象的属性名)
源/目标 属性类型 (多则集合/少则对象
联接列 必须选中 源的表字段/目标的表字段 两者是外键关系(一定要是外键关系
多对多情况:需要手动指定联接表(第三表)进行对两表的进行连接
需要手动确认4个列 分别为 ==源id / 第三表外键源id / 目标id / 第三表外键目标id==
# 关联映射
在关联映射当中有三种形式,分别为:
- 一对一
- 一对多
- 多对多
# 一对多
一方: 多方 的实体集合 ,通过标签 <set>
完成
多方: 一方 的实体类,通过标签 <many-to-one>
必要标签说明:
<many-to-one>
:多对一
name
:关联对象的属性名column
:实体类对应的外键表字段名class
:关联对象类(全限定名
<set>
:一对多
name
:关联对象属性名<key>.column
:关联对象的外键名<one-to-many>.class
:关联对象类(全限定名
一般情况会反向自动生成的xml
联级操作:
<set>.cascade
:联级操作
delete
:联级删除all
: 联级增删改sace-update
:联级 增加/修改
一对多示例:(部门一 - 员工多)
Staff员工表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
id | int | - | key |
name | varchar | 名称 | - |
deptId | int | 部门id | dept.id |
Dept部门表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
id | int | - | key |
name | varchar | 部门名称 | - |
Staff员工实体-xml配置
// Staff.java 员工实体对象
public class Staff {
private int id;
private String name;
// 主要关系对象
private Dept dept;
//get、set配置。。。
}
....
<!-- Staff.hbm.xml 配置 -->
<hibernate-mapping>
<!-- oneToMany.Staff 包路径 / staff 表名 -->
<class name="oneToMany.Staff" table="staff">
<id name="id" column="id">
<generator class="increment"></generator>
</id>
<property name="name"></property>
<!--
name: Staff实体类中的dept属性
column: 子表中被外键约束修饰的字段名
class: Staff相关联的Dept类
-->
<many-to-one name="dept" column="deptId" class="oneToMany.Dept"></many-to-one>
</class>
</hibernate-mapping>
Dept员工实体-xml配置
public class Dept {
private int id;
private String name;
// 建议手动创建初始化集合对象
private Set<Staff> staffSet = new HashSet<>(0);
// get、set配置。。。
}
....
<!-- Staff.hbm.xml 配置 -->
<hibernate-mapping>
<class name="oneToMany.Dept" table="dept">
<id name="id" column="id">
<generator class="increment"></generator>
</id>
<property name="name"></property>
<!-- key:子表被外键约束修饰的字段名 -->
<set name="staffSet" cascade="all">
<key column="deptId"/>
<one-to-many class="oneToMany.Staff"/>
</set>
</class>
</hibernate-mapping>
测试访问:
// 多对一
@Test
public void add(){
// 假设已经获取到了 Session 对象
//创建新部门
Dept dept = new Dept();
dept.setName("er部门");
//创建新的职员
Staff staff = new Staff();
staff.setName("www");
//给职员中添加部门
staff.setDept(dept);
//给部门中添加职员
dept.getStaffSet().add(staff);
//保存部门
session.save(dept);
}
@Test
public void del(){
// 假设已经获取到了 Session 对象
// 指定查询id : 2
Dept dept = (Dept) sesslin.get(Dept.class,2);
session.delete(dept);
// 删除会连同指定相同的id:2的部门一起删除
}
@Test
public void find(){
// 假设已经获取到了 Session 对象
Dept dept = (Dept) sesslin.get(Dept.class,2);
System.out.println(dept);
for(Staff staff : detp.getSeaff()){
System.out.println(staff);
}
}
# 多对多
多对多关系 是两表之间对多关系,通常会以第三表为中间作为两表联系的关系表。两张表都只和关系表间建立主外键关系!
<many-to-many>
:多对多
name
:关联对象的属性名column
:实体类对应的外键表字段名class
:关联对象类(全限定名
应用说明:
- 多对多的应用 也需要 cascade 联级操作 的操作
Menu菜单表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
m_id | int | - | key |
m_name | varchar | 菜单名称 | - |
m_state | int | 状态 | - |
Role角色表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
r_id | int | - | key |
r_name | varchar | 角色名称 | - |
r_state | int | 状态 | - |
关系表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
id | int | - | key |
m_id | int | 菜单id | menu.id |
r_id | int | 角色id | role.id |
Role角色实体-xml配置
public class Role {
private int rId;
private String rName;
private Integer rState;
private Set<Menu> menus = new HashSet<>(0);
// get/set ...
}
...
<!-- Role.hbm.xml 配置 -->
<hibernate-mapping>
<!-- com.sans.pojo.Role 包路径 / role 表名 / hospital 数据库名 -->
<class name="com.sans.pojo.Role" table="role" schema="hospital">
<id name="rId">
<column name="r_id" sql-type="int"/>
<generator class="native"/>
</id>
<property name="rName">
<column name="r_name" sql-type="varchar(80)" length="80" not-null="true"/>
</property>
<property name="rState">
<column name="r_state" sql-type="int" not-null="true"/>
</property>
<!-- 联级操作第三表 需要配置 cascade="all" -->
<set name="menus" table="role_menu" cascade="all">
<!-- 外键字段 -->
<key column="r_id"/>
<!-- 集合对应的实体类 -->
<many-to-many class="com.sans.pojo.Menu" column="m_id"/>
</set>
</class>
</hibernate-mapping>
Menu菜单实体-xml配置
public class Menu {
private int mId;
private String mName;
private Integer mState;
private Set<Role> roles = new HashSet<>(0);
// get/set ...
}
....
<!-- Menu.hbm.xml 配置 -->
<hibernate-mapping>
<class name="com.sans.pojo.Menu" table="menu" schema="hospital">
<id name="mId">
<column name="m_id" sql-type="int"/>
<generator class="native"/>
</id>
<property name="mName">
<column name="m_name" sql-type="varchar(80)" length="80" not-null="true"/>
</property>
<property name="mState">
<column name="m_state" sql-type="int" not-null="true"/>
</property>
<!-- 联级操作第三表 需要配置 cascade="all" -->
<set name="roles" table="role_menu" cascade="all">
<!-- 外键字段 -->
<key column="m_id"/>
<!-- 集合对应的实体类 -->
<many-to-many class="com.sans.pojo.Role" column="r_id"/>
</set>
</class>
</hibernate-mapping>
测试:
@Test
public void findByMenu() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Menu menu = (Menu) session.get(Menu.class , 4);
System.out.println("menu : " + menu);
System.out.println("menu.roles : " + menu.getRoles());
tx.commit();
HibernateUtil.close();
}
@Test
public void findByRole() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Role role = (Role) session.get(Role.class,1);
System.out.println("role : " + role);
System.out.println("role.menus : " + role.getMenus());
tx.commit();
HibernateUtil.close();
}
// 联级添加
@Test
public void add() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Menu menu = new Menu("xx管理",22);
System.out.println("menu : " + menu);
Role role1 = new Role("医生",1);
Role role2 = new Role("主管",1);
menu.getRoles().add(role1);
menu.getRoles().add(role2);
session.save(menu);
tx.commit();
session.close();
}
// 联级删除
@Test
public void del() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
// 根据指定的 Role.id进行删除
Role role = new Role();
role.setrId(39);
// 指定 Menu.id进行删除
// Menu menu = new Menu();
// menu.setmId(23);
session.delete(role);
tx.commit();
HibernateUtil.close();
}
# 高级查询
Hibernate 框架 提供了两个用于查询的对象分别为 Query、Criteria对象
Criteria对象 应用起来方法较多,自行了解:
https://www.w3cschool.cn/hibernate/ugov1ie8.html
# Query
query查询方式 依靠自行编写的 hql语句进行查询数据
query对象获取
==Session.createQuery(String hql)==
query常用方法
获取结果集方法
返回 | 方法 | 说明 |
---|---|---|
R | uniqueResult() | 查询结果的单条数据,没有则null |
List<R> | list() | 查询结果集以list形式的结果 |
Iterator<R> | iterate() | 查询结果集以迭代器形式的结果 |
**注意:**list()方法 返回的数据 如果不为 实体对象的属性,那么它返回的是
Object[]
数组
其他方法
返回 | 方法 | 说明 |
---|---|---|
Query | setXX( String/int , XX) (XX为数据类型名) | 填充hql语句的 数据/占位符 |
Query | setFirstResult(int firstResult) | 设置 查询起始行数 |
Query | setMaxResults(int maxResults) | 设置 查询最大行数 |
更多方法可以在自行查看源码
query查询示例
示例说明:
- 仅展现功能代码块
- 两表关系为 一对多 (一部门 - 多员工)
dept部门表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
deptno | int | id | key |
dname | varchar | 部门名 | - |
loc | varhcar | 区 | - |
emp员工表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
empno | int | id | key |
ename | varchar | 员工名称 | - |
sal | decimal (浮点型 | 工资 | - |
deptno | int | 部门id | dept.deptno |
public class Demo {
// 对象查询
@Test
public void test01() {
// 查 部门对象
String hql = "from Dept";
Session session = HibernateUtil.getSession();
Query query = session.createQuery(hql);
List<Dept> list = query.list();
for (Dept dept : list) {
System.out.println("dept : " + dept);
}
}
// 属性查询
@Test
public void test02() {
// 查 指定部门
String hql = "select loc,deptno from Dept";
Session session = HibernateUtil.getSession();
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
for (Object[] row : list) {
System.out.println(row[0] + "\t - \t" + row[1]);
}
HibernateUtil.close();
}
// 约束查询1
@Test
public void test03() {
String hql = "from Dept where dname = ?";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
query.setString(0 , "会计部");
List<Dept> list = query.list();
for (Dept dept : list) {
System.out.println(dept);
}
tx.commit();
HibernateUtil.close();
}
// 约束查询2
@Test
public void test04() {
String hql = "from Dept where dname = :name ";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
query.setString("name" , "会计部");
List<Dept> list = query.list();
for (Dept dept : list) {
System.out.println(dept);
}
tx.commit();
HibernateUtil.close();
}
// 模糊查询
@Test
public void test11() {
String hql = "from Emp where ename like :name";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
// 注意:不能含有单引号直接引用
String name = "张";
query.setString("name","%"+name+"%");
List<Emp> list = query.list();
for (Emp emp : list) {
System.out.println(emp);
}
tx.commit();
HibernateUtil.close();
}
// 聚合查询
@Test
public void test05() {
String hql = "select count(*) from Dept";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
Long count = (Long) query.uniqueResult();
System.out.println("count : " + count);
tx.commit();
HibernateUtil.close();
}
// 分页查询
@Test
public void test06() {
String hql = "from Emp";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
int index = 2;
int pageSize = 5;
// 指定 起始位置 和 总量
query.setFirstResult((index - 1) * pageSize);
query.setMaxResults(pageSize);
List<Emp> list = query.list();
for (Emp e : list) {
System.out.println(e);
}
tx.commit();
HibernateUtil.close();
}
// 内连接
@Test
public void test07() {
String hql = "from Emp e inner join e.dept";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
// 将 emp的外键 deptno结合 dept 连接查询
List<Object[]> list = query.list();
for (Object[] row : list) {
Emp emp = (Emp) row[0];
Dept dept = (Dept) row[1];
System.out.println("==========");
System.out.println("emp : " + emp);
System.out.println("dept : " + dept);
}
tx.commit();
HibernateUtil.close();
}
// 追切内连接
// 解决封装的问题
@Test
public void test08() {
String hql = "from Emp e inner join fetch e.dept";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
List<Emp> list = query.list();
for (Emp emp : list) {
System.out.println(emp);
}
tx.commit();
HibernateUtil.close();
}
// 左外连接
@Test
public void test09() {
String hql = "from Dept d left outer join d.emps";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
for (Object[] row : list) {
Dept dept = (Dept) row[0];
Emp emp = (Emp) row[1];
System.out.println("dept : " + dept.getDname());
if (emp != null) {
System.out.println(" | "+emp);
}else{
System.out.println(" | 无员工");
}
}
tx.commit();
HibernateUtil.close();
}
// 追切左连接
@Test
public void test10() {
String hql = "select distinct d from Dept d left outer join fetch d.emps";
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery(hql);
List<Dept> list = query.list();
for (Dept dept : list) {
System.out.println("dept : " + dept.getDname());
Set<Emp> emps = dept.getEmps();
if (emps != null && emps.size() > 0) {
for (Emp emp : emps) {
System.out.println("\t" + emp.getEname());
}
} else {
System.out.println("\t无员工");
}
}
tx.commit();
HibernateUtil.close();
}
}
# Criteria
org.hibernate.Criteria
是 面向对象的方式在进行数据查询,无需手写hql语句
特点:
- 面向对象查询
- 摆脱hql语句拼接的应用
Criteria对象获取
==Session.createCriteria(Class Bean)==
常用方法
获取结果集
返回 | 方法 | 说明 |
---|---|---|
List | list() | 获取结果集列表 |
Object | uniqueResult() | 获取单个结果,没有则null |
查询约束
返回 | 方法 | 参数 | 说明 |
---|---|---|---|
Criterion | add(Criterion criterion) | 约束criterion对象 | 添加 约束条件 |
Criterion | setMaxResults(int maxResults) | 行最大值 | 设置 查询最大行数 |
Criterion | setFirstResult(int firstResult) | 行起始值 | 设置 查询起始行数 |
Criterion | createCriteria(String associationPath) | 属性数据集名称 | 添加数据集 内连接 |
org.hibernate.criterion.Criterion
约束对象(一般应用传递约束
org.hibernate.criterion.Restrictions
标准约束对象
Restrictions对象 内置封装了常用约束静态方法
常用约束方法
返回 | 方法 | 说明 |
---|---|---|
Criterion | idEq(Object value) | 比较id |
Criterion | eq(String propertyName, Object value) | 比较指定属性 |
Criterion | like(String propertyName, Object value) | 模糊指定属性 |
Criterion | ilike(String propertyName, Object value) | 模糊指定属性(省略大小写 |
Criterion | and(Criterion lhs, Criterion rhs) | 合并约束(同时满足) |
Criterion | or(Criterion lhs, Criterion rhs) | 满足约束(其中满足) |
Criterion | not(Criterion expression) | 约束取反(满足取反) |
Criterion | between(String propertyName, Object lo, Object hi) | 选区范围值 |
.... | .... | .... |
方法比较多 自行查询API
org.hibernate.criterion.Example
实例对象约束
Example对象 内置实例对象查询的方法一般情况直接写入实例对象即可
// sfrom emp
List results = session.createCriteria(Emp.class)
.add( Example.create(emp).ignoreCase())
.list();
示例:
数据库表
dept部门表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
deptno | int | id | key |
dname | varchar | 部门名 | - |
loc | varhcar | 区 | - |
emp员工表
字段名 | 类型 | 说明 | 外键 |
---|---|---|---|
empno | int | id | key |
ename | varchar | 员工名称 | - |
sal | decimal (浮点型 | 工资 | - |
deptno | int | 部门id | dept.deptno |
PS:由于员工的工资属性sal 应用的是 BigDecimal 数据类型
// 普通类表查询
@Test
public void test01() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Criteria cr = session.createCriteria(Emp.class);
List<Emp> list = cr.list();
for (Emp emp : list) {
System.out.println(emp);
}
tx.commit();
HibernateUtil.close();
}
// 约束查询
@Test
public void test02() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Criteria cr = session.createCriteria(Emp.class);
// 约束查 大于等于
cr.add(Restrictions.ge("sal",new BigDecimal(5000)));
List<Emp> list = cr.list();
for (Emp emp : list) {
System.out.println(emp);
}
tx.commit();
HibernateUtil.close();
}
// 实例查询
@Test
public void test03() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Criteria cr = session.createCriteria(Emp.class);
Emp emp = new Emp();
emp.setJob("CLERK");
cr.add(Example.create(emp));
List<Emp> list = cr.list();
for (Emp e : list) {
System.out.println(e);
}
tx.commit();
HibernateUtil.close();
}
// 链式内连接查询
@Test
public void test04() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
List<Dept> depts =
session.createCriteria(Dept.class)
.add(Restrictions.eq("dname","cqc"))
.createCriteria("emps")
.add(Restrictions.eq("ename","j4"))
.list();
for (Dept dept : depts) {
System.out.println(dept);
}
tx.commit();
HibernateUtil.close();
}
// 表达式and约束查询
@Test
public void test05() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
// 查工资大于5k 且 职位为 CLERK
Criterion crSal = Restrictions.gt("sal",new BigDecimal(5000));
Criterion crJob = Restrictions.eq("job","CLERK");
List<Emp> emps =
session.createCriteria(Emp.class)
.add(Restrictions.and(crSal,crJob))
.list();
for (Emp emp : emps) {
System.out.println(emp);
}
tx.commit();
HibernateUtil.close();
}
# 缓存机制
# 一级缓存
Hibernate一级缓存是强制性的缓存,在 Session层(会话)
**清空缓存条件:**Session关闭、数据更变
# 二级缓存
Hibernate一级缓存是选择性的缓存,主要负责跨会话缓存对象。
需要直接配置策略
# Hibernate问题
hql语句 问题
- hql语句中的 表名的首字母一定要大写 (因:与类名一致,否则找不着
- 遵守数据库命名规则
联级操作 问题
要手动添加
<set>.cascade
属性/<generator>.class
id自增策略 的应用(因:反向生成不会生成在联级添加数据时,尽可能避免指定外键id值添加数据(因:id值约束可能影响数据的添加
在联级添加数据时,一方 配置的
<set>.inverse
属性为true ,会产生二级数据的外键id为空,解决方式方案:将含有主键的一方设为 关系维护方即可原因: 以上的设置是 将 一方的 关系维护 交给多方管理,那么多方 在插入数据时会 根据对象的联级关系进行插入的,而一方的主键id生成在写入数据库之后生成的,因此二级的外键id为空
在联级删除 多的一方,
<set>.cascade
属性值不能为none在联级删除 单的一方时,不能含有该属性
cascade
反向生成 问题
- 反向生成xml,不会生成
<generator>.class
id自增策略(因:id可能会相同导致异常 - 反向生成实体对象,实体对象的 对多关系 的 集合数据 需要初始化 (因:不初始化联级操作可能会出现异常
- 反向生成xml,不会生成
对多数据 问题
- 多对一 查询:
<many-to-one>
标签 添加 ==insert="false" update="false"==属性(因:在查询中可能会出现重复列的问题 - 多对多 删除:多对多含有关系表的情况下,只要一方的数据被删除完,另一方还会存在数据指定的是双方的外键id(因:两表的外键约束的在第三方的关系表中,因此两表的是互补干扰的!
- 多对一 查询: