主流的ORM(Object Relation Mapping:对象关系映射)框架,将面向对象映射成面向关系
一 Hibernate第一天
JavaEE的三层结构
- web层(视图层)
- servicer层(服务层)
- dao层(持久层)
MVC思想:
- M:模型
- V:视图
- C:控制器
1 hibernate概述
hibernate是应用在dao层中hibernate底层代码就是jdbc,不需要写sql语句实现hibernate开源轻量级框架
2 hibernate入门案例
- 导入相关依赖
- 创建Hibernate配置文件
- 创建实体类
- 创建实体类-关系映射文件
- 调用HibernateAPI完成操作
3 hibernate配置文件
Maven
<dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.17</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.4.10.Final</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version></dependency></dependencies><!--允许读取src下面的xml文件--><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource></resources></build>
hibernate.cfg.xml
// 核心配置:session-factory// SessionFactory:针对单个数据库映射经过编译的内存镜像文件,将数据库转换为一个Java可以识别的镜像文件// 构建SessionFatory非常耗费资源,所以通常一个工程只需要创建一个SessionFactory<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- 数据源的配置 --><property name="connection.username">root</property><property name="connection.password">root</property><property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property><property name="connection.url">jdbc:mysql://localhost:3306/test?userUnicode&characterEncoding=UTF-8</property><!-- C3P0连接池 --><property name="hibernate.c3p0.acquire_increment">10</property><property name="hibernate.c3p0.idle_test_period">10000</property><property name="hibernate.c3p0.timeout">5000</property><property name="hibernate.c3p0.max_size">30</property><property name="hibernate.c3p0.min_size">5</property><property name="hibernate.c3p0.max_statements">10</property><!-- 数据库方言 --><property name="dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 打印sql --><property name="show_sql">true</property><!-- 格式化sql --><property name="format_sql">true</property><!-- 是否自动生成数据表 --><property name="hibernate.hbm2ddl.auto"></property></session-factory></hibernate-configuration>
4 创建实体关系映射文件
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.wackyboy.domain.Customer" table="customer"><id name="id" type="java.lang.Integer"><column name="id"></column><generator class="identity"></generator></id><property name="name" type="java.lang.String"><column name="name"></column></property></class></hibernate-mapping>
5 实体关系映射文件注册到Hibernate的配置文件中
<!-- 注册实体关系映射文件 --><mapping resource="com/wackyboy/domain/People.hbm.xml"></mapping>
6 使用HibernateAPI完成数据操作
package com.wackyboy.test;import com.wackyboy.domain.People;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;/*** @Author: WackyBoy* @Date: 2021/3/4 20:40*/public class Test {public static void main(String[] args) {// 创建ConfigurationConfiguration cfg = new Configuration().configure();// 获取SessionFactorySessionFactory sessionFactory = cfg.buildSessionFactory();// 获取Session对象Session session = sessionFactory.openSession();People people = new People();people.setName("张三");people.setMoney(10000);session.save(people);// 事务的提交session.beginTransaction().commit();session.close();}}
二 第二天
1 Hibernate的级联操作
一对多关系
客户和订单:客户一订单多
package com.wackyboy.domain;import lombok.Data;import java.util.Set;/*** @Author: WackyBoy* @Date: 2021/3/4 19:33*/@Datapublic class Customer {private Integer id;private String name;private Set<Orders> orders;}
package com.wackyboy.domain;import lombok.Data;/*** @Author: WackyBoy* @Date: 2021/3/4 19:54*/@Datapublic class Orders {private Integer id;private String name;private Customer customer;}
多对多关系
学生选课:一门课可被多人选择,一个可选择多门课程
数据库中是通过两个一对多关系来维护的, 学生和课程都是主表,额外增加一张中间表作为从表,两张主表和中间表都是一对多的关系
package com.wackyboy.domain;import lombok.Data;import java.util.Set;/*** @Author: WackyBoy* @Date: 2021/3/4 21:24*/@Datapublic class Account {private Integer id;private String name;private Set<Course> courses;}
package com.wackyboy.domain;import java.util.Set;/*** @Author: WackyBoy* @Date: 2021/3/4 21:26*/public class Course {private Integer id;private String name;private Set<Account> accounts;}
2 Hibernate实现一对多
Customer的配置:
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.wackyboy.domain.Customer" table="customer"><id name="id" type="java.lang.Integer"><column name="id"></column><generator class="identity"></generator></id><property name="name" type="java.lang.String"><column name="name"></column></property><set name="orders" table="orders"><key column="cid"></key><one-to-many class="com.wackyboy.domain.Orders"></one-to-many></set></class></hibernate-mapping>
- set标签来配置实体类中集合属性orders
- name实体类属性名
- table表名
- key外键
- one-to-many与集合泛型的实体类对应
Order的配置:
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.wackyboy.domain.Orders" table="orders"><id name="id" type="java.lang.Integer"><column name="id"></column><generator class="identity"></generator></id><property name="name" type="java.lang.String"><column name="name"></column></property><many-to-one name="customer" class="com.wackyboy.domain.Customer" column="cid"></many-to-one></class></hibernate-mapping>
- many-to-one配置实体类对应的对象属性
- name属性名
- class属性对应的类
- column外键
需要在Hiberbate配置文件中进行注册
<!-- 注册实体关系映射文件 --><mapping resource="com/wackyboy/domain/People.hbm.xml"></mapping><mapping resource="com/wackyboy/domain/Customer.hbm.xml"></mapping><mapping resource="com/wackyboy/domain/Orders.hbm.xml"></mapping>
HibernateAPi调用
package com.wackyboy.test;import com.sun.org.apache.xpath.internal.operations.Or;import com.wackyboy.domain.Customer;import com.wackyboy.domain.Orders;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;/*** @Author: WackyBoy* @Date: 2021/3/4 21:54*/public class Test2 {public static void main(String[] args) {// 创建ConfigurationConfiguration cfg = new Configuration().configure();// 获取SessionFactorySessionFactory sessionFactory = cfg.buildSessionFactory();// 获取Session对象Session session = sessionFactory.openSession();// 创建Customer对象Customer customer = new Customer();customer.setName("李四");// 创建OrdersOrders orders = new Orders();orders.setName("订单1");// 建立关联关系orders.setCustomer(customer);// 保存session.save(customer);session.save(orders);// 提交事务session.beginTransaction().commit();session.close();}}
3 Hibernate实现多对多
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.wackyboy.domain.Account" table="t_account"><id name="id" type="java.lang.Integer"><column name="id"></column><generator class="identity"></generator></id><property name="name" type="java.lang.String"><column name="name"></column></property><set name="courses" table="account_course"><key column="aid"></key><many-to-many class="com.wackyboy.domain.Course" column="cid"></many-to-many></set></class></hibernate-mapping>
- name实体类对应的集合属性名
- table中间表名
- key外键
- many-to-many与集合泛型的实体类对应
- column属性与中间表的外键字段名对应
- 注册到Hibernate配置文件中
package com.wackyboy.test;import com.wackyboy.domain.Account;import com.wackyboy.domain.Course;import com.wackyboy.domain.Customer;import com.wackyboy.domain.Orders;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import java.util.HashSet;import java.util.Set;/*** @Author: WackyBoy* @Date: 2021/3/4 21:54*/public class Test3 {public static void main(String[] args) {// 创建ConfigurationConfiguration cfg = new Configuration().configure();// 获取SessionFactorySessionFactory sessionFactory = cfg.buildSessionFactory();// 获取Session对象Session session = sessionFactory.openSession();Course course = new Course();course.setName("Java");Account account = new Account();account.setName("tiantian");Set<Course> courses = new HashSet<Course>();courses.add(course);account.setCourses(courses);session.save(course);session.save(account);// 提交事务session.beginTransaction().commit();session.close();}}
三 第三天
1 Hibernate的延迟加载
延迟加载、惰性加载、懒加载
使用延迟加载么一提高程序的运行效率,Java程序与数据库交互的频次越低,程序的运行效率越高,Hibernate的延迟加载很好的做到了这一点
场景
- 客户和订单,当我们查询客户对象的时候,因为有级联设置,所以会将对应的订单信息一并查询出来,这样就需要发送两条SQL语句,分别查询客户信息和订单信息
- 延迟加载的思路:当我们查询客户的时候,如果没有访问订单的数据,只发送一条SQL语句查询客户的信息,如果需要访问订单数据,则发送两条SQL
- 延迟加载可以看作是一种优化机制,根据具体的需求,自动选择要执行得到SQL语句数量
案例一:一对多
- 查询Customer,对Orders进行延迟加载设置,在customer.hbm.xml中进行设置, 延迟加载默认开启
<set name="orders" table="orders" lazy="true"><key column="cid"></key><one-to-many class="com.wackyboy.domain.Orders"></one-to-many></set>
- 查询Customer
/*** @Author: WackyBoy* @Date: 2021/3/4 21:54*/public class Test4 {public static void main(String[] args) {// 创建ConfigurationConfiguration cfg = new Configuration().configure();// 获取SessionFactorySessionFactory sessionFactory = cfg.buildSessionFactory();// 获取Session对象Session session = sessionFactory.openSession();Customer customer = session.get(Customer.class, 4);System.out.println(customer);Sytem.out.println(customer.getOrders());session.close();}}
lazy 除了可以设置true个false之外,还可以设置extra,extra是比true更加懒惰的一种加载方式,或者说是更加只能的一种加载方式
也可以通过Orders来设置Customer的延迟加载,orders.hbm.xml中进行设置, lazy=”proxy”
<many-to-one name="customer" class="com.wackyboy.domain.Customer" column="cid" lazy="proxy"></many-to-one>
- no-proxy:当调用方法需要访问customer的成员变量时,发送SQl语句查询Customer,否则不查询
- proxy:无论调用的方法需要访问customer的成员变量,都会发送SQL语句查询
案例二:多对多
2 Hibernate的配置文件
<hibernate-configuration><session-factory><!-- 数据源的配置 --><property name="connection.username">root</property><property name="connection.password">root</property><property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property><property name="connection.url">jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&userUnicode&characterEncoding=UTF-8</property><!--serverTimezone=Asia/Shanghai--><!-- C3P0连接池 --><property name="hibernate.c3p0.acquire_increment">10</property><property name="hibernate.c3p0.idle_test_period">10000</property><property name="hibernate.c3p0.timeout">5000</property><property name="hibernate.c3p0.max_size">30</property><property name="hibernate.c3p0.min_size">5</property><property name="hibernate.c3p0.max_statements">10</property><!-- 数据库方言 --><property name="dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 打印sql --><property name="show_sql">true</property><!-- 格式化sql --><property name="format_sql">true</property><!-- 是否自动生成数据表 --><property name="hibernate.hbm2ddl.auto"></property><!-- 注册实体关系映射文件 --><mapping resource="com/wackyboy/domain/People.hbm.xml"></mapping><mapping resource="com/wackyboy/domain/Customer.hbm.xml"></mapping><mapping resource="com/wackyboy/domain/Orders.hbm.xml"></mapping><mapping resource="com/wackyboy/domain/Account.hbm.xml"></mapping><mapping resource="com/wackyboy/domain/Course.hbm.xml"></mapping></session-factory></hibernate-configuration>
- hibernate.xml:配置Hibernate的全局环境
- 数据库的基本信息
- 继承C3P0,设置数据库连接信息
- Hibernate的基本信息
- 注册实体关系映射文件
- hbm.xml:实体关系映射文件
- hibernate-mapping
- package:实体类对应的包名
- schema:数据库schema的名称
- catalog:数据库catalog的名称
- default-cascade:默认的级联关系,默认为none
- default-access:Hibernate用来访问属性的策略
- default-lazy:指定了未明确著名lazy属性的Java属性和集合类,Hibernate会采用什么样的加载风格,默认为true
- auto-import:指定我们是否可以在查询语句中使用非全限定类名,默认为true,如果项目中有两个同名的持久化类,最好在这两个对应的映射文件中配置为false
- class属性:
- name
- table
- schema:数据库schema的名称,会覆盖上级
- catalog:数据库catalog的名称,同上
- proxy:指定一个接口,在延迟加载时作为代理使用
- dynamic-update:动态更新
- dynamic-insert:动态添加
- where:查询时给SQL添加where条件
- id属性
- name:实体类属性名
- type:实体类属性数据类型,此处可以设置两种类型的数据:Java数据类型或者Hibernate映射类型,实体类的属性护具类型必须与数据表对应的字段类型一致
- Java数据类型映射到Hibernate映射类型,再由Hibernate映射类型映射到SQL数据类型上
- column:数据表的主键字段名
- generator:主键生成策略
- hilo算法
- increment:Hinerbate自增
- identity:数据库自增
- native:本地策略,根据底层数据库自动选择主键的生成策略
- uuid.hex算法
- select算法
- property属性
- name:实体类的属性名
- column:
- hibernate-mapping
<class name="com.wackyboy.domain.People" table="people" dynamic-insert="true" dynamic-update="true">
<class name="com.wackyboy.domain.People" table="people" dynamic-insert="true" where="id = 1">
package com.wackyboy.test;import com.wackyboy.domain.Orders;import com.wackyboy.domain.People;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.hibernate.query.Query;import java.util.List;/*** @Author: WackyBoy* @Date: 2021/3/4 21:54*/public class Test6 {public static void main(String[] args) {// 创建ConfigurationConfiguration cfg = new Configuration().configure();// 获取SessionFactorySessionFactory sessionFactory = cfg.buildSessionFactory();// 获取Session对象Session session = sessionFactory.openSession();String hql = "from People";Query query = session.createQuery(hql);List<People> list = query.list();for(People people : list) {System.out.println(people);}session.beginTransaction().commit();session.close();}}
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.wackyboy.domain"><class name="Course" table="t_course"><id name="id" type="java.lang.Integer"><column name="id"></column><generator class="identity"></generator></id><property name="name" type="java.lang.String"><column name="name"></column></property><set name="accounts" table="account_course"><key column="cid"></key><many-to-many class="Account" column="aid"></many-to-many></set></class></hibernate-mapping>
