主流的ORM(Object Relation Mapping:对象关系映射)框架,将面向对象映射成面向关系

一 Hibernate第一天

JavaEE的三层结构

  1. web层(视图层)
  2. servicer层(服务层)
  3. dao层(持久层)

MVC思想:

  1. M:模型
  2. V:视图
  3. C:控制器

1 hibernate概述

  1. hibernate是应用在dao层中
  2. hibernate底层代码就是jdbc,不需要写sql语句实现
  3. hibernate开源轻量级框架

2 hibernate入门案例

  • 导入相关依赖
  • 创建Hibernate配置文件
  • 创建实体类
  • 创建实体类-关系映射文件
  • 调用HibernateAPI完成操作

3 hibernate配置文件

Maven

  1. <dependencies>
  2. <dependency>
  3. <groupId>mysql</groupId>
  4. <artifactId>mysql-connector-java</artifactId>
  5. <version>8.0.17</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.hibernate</groupId>
  9. <artifactId>hibernate-core</artifactId>
  10. <version>5.4.10.Final</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.projectlombok</groupId>
  14. <artifactId>lombok</artifactId>
  15. <version>1.18.10</version>
  16. </dependency>
  17. </dependencies>
  18. <!--允许读取src下面的xml文件-->
  19. <build>
  20. <resources>
  21. <resource>
  22. <directory>src/main/java</directory>
  23. <includes>
  24. <include>**/*.xml</include>
  25. </includes>
  26. </resource>
  27. </resources>
  28. </build>

hibernate.cfg.xml

  1. // 核心配置:session-factory
  2. // SessionFactory:针对单个数据库映射经过编译的内存镜像文件,将数据库转换为一个Java可以识别的镜像文件
  3. // 构建SessionFatory非常耗费资源,所以通常一个工程只需要创建一个SessionFactory
  4. <?xml version="1.0" encoding="UTF-8"?>
  5. <!DOCTYPE hibernate-configuration PUBLIC
  6. "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  7. "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
  8. <hibernate-configuration>
  9. <session-factory>
  10. <!-- 数据源的配置 -->
  11. <property name="connection.username">root</property>
  12. <property name="connection.password">root</property>
  13. <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
  14. <property name="connection.url">jdbc:mysql://localhost:3306/test?userUnicode&amp;characterEncoding=UTF-8</property>
  15. <!-- C3P0连接池 -->
  16. <property name="hibernate.c3p0.acquire_increment">10</property>
  17. <property name="hibernate.c3p0.idle_test_period">10000</property>
  18. <property name="hibernate.c3p0.timeout">5000</property>
  19. <property name="hibernate.c3p0.max_size">30</property>
  20. <property name="hibernate.c3p0.min_size">5</property>
  21. <property name="hibernate.c3p0.max_statements">10</property>
  22. <!-- 数据库方言 -->
  23. <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
  24. <!-- 打印sql -->
  25. <property name="show_sql">true</property>
  26. <!-- 格式化sql -->
  27. <property name="format_sql">true</property>
  28. <!-- 是否自动生成数据表 -->
  29. <property name="hibernate.hbm2ddl.auto"></property>
  30. </session-factory>
  31. </hibernate-configuration>

4 创建实体关系映射文件

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping>
  6. <class name="com.wackyboy.domain.Customer" table="customer">
  7. <id name="id" type="java.lang.Integer">
  8. <column name="id"></column>
  9. <generator class="identity"></generator>
  10. </id>
  11. <property name="name" type="java.lang.String">
  12. <column name="name"></column>
  13. </property>
  14. </class>
  15. </hibernate-mapping>

5 实体关系映射文件注册到Hibernate的配置文件中

  1. <!-- 注册实体关系映射文件 -->
  2. <mapping resource="com/wackyboy/domain/People.hbm.xml"></mapping>

6 使用HibernateAPI完成数据操作

  1. package com.wackyboy.test;
  2. import com.wackyboy.domain.People;
  3. import org.hibernate.Session;
  4. import org.hibernate.SessionFactory;
  5. import org.hibernate.cfg.Configuration;
  6. /**
  7. * @Author: WackyBoy
  8. * @Date: 2021/3/4 20:40
  9. */
  10. public class Test {
  11. public static void main(String[] args) {
  12. // 创建Configuration
  13. Configuration cfg = new Configuration().configure();
  14. // 获取SessionFactory
  15. SessionFactory sessionFactory = cfg.buildSessionFactory();
  16. // 获取Session对象
  17. Session session = sessionFactory.openSession();
  18. People people = new People();
  19. people.setName("张三");
  20. people.setMoney(10000);
  21. session.save(people);
  22. // 事务的提交
  23. session.beginTransaction().commit();
  24. session.close();
  25. }
  26. }

二 第二天

1 Hibernate的级联操作

一对多关系

客户和订单:客户一订单多

  1. package com.wackyboy.domain;
  2. import lombok.Data;
  3. import java.util.Set;
  4. /**
  5. * @Author: WackyBoy
  6. * @Date: 2021/3/4 19:33
  7. */
  8. @Data
  9. public class Customer {
  10. private Integer id;
  11. private String name;
  12. private Set<Orders> orders;
  13. }
  1. package com.wackyboy.domain;
  2. import lombok.Data;
  3. /**
  4. * @Author: WackyBoy
  5. * @Date: 2021/3/4 19:54
  6. */
  7. @Data
  8. public class Orders {
  9. private Integer id;
  10. private String name;
  11. private Customer customer;
  12. }

多对多关系

学生选课:一门课可被多人选择,一个可选择多门课程
数据库中是通过两个一对多关系来维护的, 学生和课程都是主表,额外增加一张中间表作为从表,两张主表和中间表都是一对多的关系

  1. package com.wackyboy.domain;
  2. import lombok.Data;
  3. import java.util.Set;
  4. /**
  5. * @Author: WackyBoy
  6. * @Date: 2021/3/4 21:24
  7. */
  8. @Data
  9. public class Account {
  10. private Integer id;
  11. private String name;
  12. private Set<Course> courses;
  13. }
  1. package com.wackyboy.domain;
  2. import java.util.Set;
  3. /**
  4. * @Author: WackyBoy
  5. * @Date: 2021/3/4 21:26
  6. */
  7. public class Course {
  8. private Integer id;
  9. private String name;
  10. private Set<Account> accounts;
  11. }

2 Hibernate实现一对多

Customer的配置:

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping>
  6. <class name="com.wackyboy.domain.Customer" table="customer">
  7. <id name="id" type="java.lang.Integer">
  8. <column name="id"></column>
  9. <generator class="identity"></generator>
  10. </id>
  11. <property name="name" type="java.lang.String">
  12. <column name="name"></column>
  13. </property>
  14. <set name="orders" table="orders">
  15. <key column="cid"></key>
  16. <one-to-many class="com.wackyboy.domain.Orders"></one-to-many>
  17. </set>
  18. </class>
  19. </hibernate-mapping>
  • set标签来配置实体类中集合属性orders
  • name实体类属性名
  • table表名
  • key外键
  • one-to-many与集合泛型的实体类对应

Order的配置:

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping>
  6. <class name="com.wackyboy.domain.Orders" table="orders">
  7. <id name="id" type="java.lang.Integer">
  8. <column name="id"></column>
  9. <generator class="identity"></generator>
  10. </id>
  11. <property name="name" type="java.lang.String">
  12. <column name="name"></column>
  13. </property>
  14. <many-to-one name="customer" class="com.wackyboy.domain.Customer" column="cid"></many-to-one>
  15. </class>
  16. </hibernate-mapping>
  • many-to-one配置实体类对应的对象属性
  • name属性名
  • class属性对应的类
  • column外键

需要在Hiberbate配置文件中进行注册

  1. <!-- 注册实体关系映射文件 -->
  2. <mapping resource="com/wackyboy/domain/People.hbm.xml"></mapping>
  3. <mapping resource="com/wackyboy/domain/Customer.hbm.xml"></mapping>
  4. <mapping resource="com/wackyboy/domain/Orders.hbm.xml"></mapping>

HibernateAPi调用

  1. package com.wackyboy.test;
  2. import com.sun.org.apache.xpath.internal.operations.Or;
  3. import com.wackyboy.domain.Customer;
  4. import com.wackyboy.domain.Orders;
  5. import org.hibernate.Session;
  6. import org.hibernate.SessionFactory;
  7. import org.hibernate.cfg.Configuration;
  8. /**
  9. * @Author: WackyBoy
  10. * @Date: 2021/3/4 21:54
  11. */
  12. public class Test2 {
  13. public static void main(String[] args) {
  14. // 创建Configuration
  15. Configuration cfg = new Configuration().configure();
  16. // 获取SessionFactory
  17. SessionFactory sessionFactory = cfg.buildSessionFactory();
  18. // 获取Session对象
  19. Session session = sessionFactory.openSession();
  20. // 创建Customer对象
  21. Customer customer = new Customer();
  22. customer.setName("李四");
  23. // 创建Orders
  24. Orders orders = new Orders();
  25. orders.setName("订单1");
  26. // 建立关联关系
  27. orders.setCustomer(customer);
  28. // 保存
  29. session.save(customer);
  30. session.save(orders);
  31. // 提交事务
  32. session.beginTransaction().commit();
  33. session.close();
  34. }
  35. }

**

3 Hibernate实现多对多

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping>
  6. <class name="com.wackyboy.domain.Account" table="t_account">
  7. <id name="id" type="java.lang.Integer">
  8. <column name="id"></column>
  9. <generator class="identity"></generator>
  10. </id>
  11. <property name="name" type="java.lang.String">
  12. <column name="name"></column>
  13. </property>
  14. <set name="courses" table="account_course">
  15. <key column="aid"></key>
  16. <many-to-many class="com.wackyboy.domain.Course" column="cid"></many-to-many>
  17. </set>
  18. </class>
  19. </hibernate-mapping>
  • name实体类对应的集合属性名
  • table中间表名
  • key外键
  • many-to-many与集合泛型的实体类对应
  • column属性与中间表的外键字段名对应
  • 注册到Hibernate配置文件中
  1. package com.wackyboy.test;
  2. import com.wackyboy.domain.Account;
  3. import com.wackyboy.domain.Course;
  4. import com.wackyboy.domain.Customer;
  5. import com.wackyboy.domain.Orders;
  6. import org.hibernate.Session;
  7. import org.hibernate.SessionFactory;
  8. import org.hibernate.cfg.Configuration;
  9. import java.util.HashSet;
  10. import java.util.Set;
  11. /**
  12. * @Author: WackyBoy
  13. * @Date: 2021/3/4 21:54
  14. */
  15. public class Test3 {
  16. public static void main(String[] args) {
  17. // 创建Configuration
  18. Configuration cfg = new Configuration().configure();
  19. // 获取SessionFactory
  20. SessionFactory sessionFactory = cfg.buildSessionFactory();
  21. // 获取Session对象
  22. Session session = sessionFactory.openSession();
  23. Course course = new Course();
  24. course.setName("Java");
  25. Account account = new Account();
  26. account.setName("tiantian");
  27. Set<Course> courses = new HashSet<Course>();
  28. courses.add(course);
  29. account.setCourses(courses);
  30. session.save(course);
  31. session.save(account);
  32. // 提交事务
  33. session.beginTransaction().commit();
  34. session.close();
  35. }
  36. }

三 第三天

1 Hibernate的延迟加载

延迟加载、惰性加载、懒加载
使用延迟加载么一提高程序的运行效率,Java程序与数据库交互的频次越低,程序的运行效率越高,Hibernate的延迟加载很好的做到了这一点

场景

  • 客户和订单,当我们查询客户对象的时候,因为有级联设置,所以会将对应的订单信息一并查询出来,这样就需要发送两条SQL语句,分别查询客户信息和订单信息
  • 延迟加载的思路:当我们查询客户的时候,如果没有访问订单的数据,只发送一条SQL语句查询客户的信息,如果需要访问订单数据,则发送两条SQL
  • 延迟加载可以看作是一种优化机制,根据具体的需求,自动选择要执行得到SQL语句数量

案例一:一对多

  1. 查询Customer,对Orders进行延迟加载设置,在customer.hbm.xml中进行设置, 延迟加载默认开启
  1. <set name="orders" table="orders" lazy="true">
  2. <key column="cid"></key>
  3. <one-to-many class="com.wackyboy.domain.Orders"></one-to-many>
  4. </set>
  1. 查询Customer
  1. /**
  2. * @Author: WackyBoy
  3. * @Date: 2021/3/4 21:54
  4. */
  5. public class Test4 {
  6. public static void main(String[] args) {
  7. // 创建Configuration
  8. Configuration cfg = new Configuration().configure();
  9. // 获取SessionFactory
  10. SessionFactory sessionFactory = cfg.buildSessionFactory();
  11. // 获取Session对象
  12. Session session = sessionFactory.openSession();
  13. Customer customer = session.get(Customer.class, 4);
  14. System.out.println(customer);
  15. Sytem.out.println(customer.getOrders());
  16. session.close();
  17. }
  18. }

lazy 除了可以设置true个false之外,还可以设置extra,extra是比true更加懒惰的一种加载方式,或者说是更加只能的一种加载方式

也可以通过Orders来设置Customer的延迟加载,orders.hbm.xml中进行设置, lazy=”proxy”

  1. <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的配置文件

  1. <hibernate-configuration>
  2. <session-factory>
  3. <!-- 数据源的配置 -->
  4. <property name="connection.username">root</property>
  5. <property name="connection.password">root</property>
  6. <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
  7. <property name="connection.url">jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&amp;userUnicode&amp;characterEncoding=UTF-8</property><!--serverTimezone=Asia/Shanghai-->
  8. <!-- C3P0连接池 -->
  9. <property name="hibernate.c3p0.acquire_increment">10</property>
  10. <property name="hibernate.c3p0.idle_test_period">10000</property>
  11. <property name="hibernate.c3p0.timeout">5000</property>
  12. <property name="hibernate.c3p0.max_size">30</property>
  13. <property name="hibernate.c3p0.min_size">5</property>
  14. <property name="hibernate.c3p0.max_statements">10</property>
  15. <!-- 数据库方言 -->
  16. <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
  17. <!-- 打印sql -->
  18. <property name="show_sql">true</property>
  19. <!-- 格式化sql -->
  20. <property name="format_sql">true</property>
  21. <!-- 是否自动生成数据表 -->
  22. <property name="hibernate.hbm2ddl.auto"></property>
  23. <!-- 注册实体关系映射文件 -->
  24. <mapping resource="com/wackyboy/domain/People.hbm.xml"></mapping>
  25. <mapping resource="com/wackyboy/domain/Customer.hbm.xml"></mapping>
  26. <mapping resource="com/wackyboy/domain/Orders.hbm.xml"></mapping>
  27. <mapping resource="com/wackyboy/domain/Account.hbm.xml"></mapping>
  28. <mapping resource="com/wackyboy/domain/Course.hbm.xml"></mapping>
  29. </session-factory>
  30. </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:
  1. <class name="com.wackyboy.domain.People" table="people" dynamic-insert="true" dynamic-update="true">
  1. <class name="com.wackyboy.domain.People" table="people" dynamic-insert="true" where="id = 1">
  1. package com.wackyboy.test;
  2. import com.wackyboy.domain.Orders;
  3. import com.wackyboy.domain.People;
  4. import org.hibernate.Session;
  5. import org.hibernate.SessionFactory;
  6. import org.hibernate.cfg.Configuration;
  7. import org.hibernate.query.Query;
  8. import java.util.List;
  9. /**
  10. * @Author: WackyBoy
  11. * @Date: 2021/3/4 21:54
  12. */
  13. public class Test6 {
  14. public static void main(String[] args) {
  15. // 创建Configuration
  16. Configuration cfg = new Configuration().configure();
  17. // 获取SessionFactory
  18. SessionFactory sessionFactory = cfg.buildSessionFactory();
  19. // 获取Session对象
  20. Session session = sessionFactory.openSession();
  21. String hql = "from People";
  22. Query query = session.createQuery(hql);
  23. List<People> list = query.list();
  24. for(People people : list) {
  25. System.out.println(people);
  26. }
  27. session.beginTransaction().commit();
  28. session.close();
  29. }
  30. }
  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping package="com.wackyboy.domain">
  6. <class name="Course" table="t_course">
  7. <id name="id" type="java.lang.Integer">
  8. <column name="id"></column>
  9. <generator class="identity"></generator>
  10. </id>
  11. <property name="name" type="java.lang.String">
  12. <column name="name"></column>
  13. </property>
  14. <set name="accounts" table="account_course">
  15. <key column="cid"></key>
  16. <many-to-many class="Account" column="aid"></many-to-many>
  17. </set>
  18. </class>
  19. </hibernate-mapping>