Hibernate 迅速搭建和初步使用

Hibernate

主流ORM框架 Object Relation Mapping 对象关系映射,将面向对象映射成面向关系。

如何使用

1、导入相关依赖

2、创建 Hibernate 配置文件

3、创建实体类

4、创建实体类-关系映射文件

5、调用 Hibernate API 完成操作

具体操作

1、创建Maven工程,pom.xml

<dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.3.10.Final</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
</dependencies>

2、创建配置文件 hibernate.cfg.xml,这个名字不能随便改

核心配置:session-factory

SessionFactory:针对单个数据映射经过编译的内存镜像文件,将数据库转换为一个Java可以识别的镜像文件。

构建 SessionFactory 非常耗费资源,所以通常一个工程只需要创建一个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.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql:///study?useUnicode=true&amp;characterEncoding=UTF-8</property>
        <property name="connection.username">root</property>
        <property name="connection.password">4444</property>

        <!-- C3P0 -->
        <property name="hibernate.c3p0.acquire_increment">10</property> <!--不够时增10个-->
        <property name="hibernate.c3p0.idle_test_period">10000</property> <!--设置失效释放资源时间-->
        <property name="hibernate.c3p0.timeout">5000</property> <!--设置超时时间-->
        <property name="hibernate.c3p0.min_size">5</property> <!--最大连接数-->
        <property name="hibernate.c3p0.max_size">30</property> <!--最小连接数-->
        <property name="hibernate.c3p0.max_statements">10</property> <!--JDBC执行sql最大限流数-->

        <!--配置方言-->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- 指定当前Session上下文为线程 -->
        <property name="current_session_context_class">thread</property>

        <!-- 控制台显示sql语句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 格式化显示 -->
        <property name="hibernate.format_sql">true</property>

        <!-- 自动建表,无则创建,有则更新 -->
        <property name="hbm2ddl.auto">update</property>

        <!-- 注册映射文件 -->
        <mapping resource="com/cqkgkj/pojo/Student.hbm.xml" />
    </session-factory>
</hibernate-configuration>

3、创建实体类

import lombok.Data;

@Data
public class Student {
    private Integer id;
    private Integer age;
    private String name;
}

4、创建实体关系映射文件,与实体在同一目录下,名字为 “实体名.hbm.xml”

<?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.cqkgkj.pojo">

    <class name="Student" table="student">
        <!-- id主键自增 -->
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" />
        <property name="age" />
    </class>

</hibernate-mapping>

5、实体关系映射文件注册到 hibernate 映射文件中

<!-- 注册映射文件 -->
<mapping resource="com/cqkgkj/pojo/Student.hbm.xml" />

6、使用 Hibernate API 完成数据操作

import com.cqkgkj.pojo.Student;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class MyTest {
    @Test
    public void test1(){
        //1.加载主配置文件与映射文件
        Configuration configure = new Configuration().configure();
        //2.创建Session工厂对象
        SessionFactory sessionFactory = configure.buildSessionFactory();
        //3.开启Session对象
        Session session = sessionFactory.getCurrentSession();
//        Session session = sessionFactory.openSession();
        try {
            //4.开启事务
            session.beginTransaction();
            Student student = new Student();
            student.setAge(22);
            student.setName("李四");
            //5.执行操作
            session.save(student);
            //6.提交事务
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            //7.回滚事务
            session.getTransaction().rollback();
        } finally {
            //8.关闭事务
            session.close();
        }
    }
}

7、pom.xml 中需要配置 resource

<!--读取java文件夹下的配置文件-->
<build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
</build>

Hibernate 级联操作

1、一对多关系

班级和学生:每个班级有多个学生,但每个学生只能属于一个班级,所以班级是一,学生是多。

数据库中一的一方是主表,多的一方是从表,通过外键关系来维护。

面向对象中

package com.cqkgkj.pojo;
import lombok.Data;
import java.util.Set;

@Data
public class Student {
    private Integer id;
    private Integer age;
    private String name;
    private Set<Class> classes;

    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

2、多对多关系

学生选课:一门课程可以被多个学生选择,一个学生可以选择多门课程,学生是多,课程也是多。

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

package com.cqkgkj.pojo;
import lombok.Data;
import java.util.Set;

@Data
public class Account {
    private Integer id;
    private String name;
    private Set<Course> courses;
}

package com.cqkgkj.pojo;
import lombok.Data;
import java.util.Set;

@Data
public class Course {
    private Integer id;
    private String name;
    private Set<Account> accounts;
}

Java 和数据库对于这两种关系的体现完全是两种不同的方式,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 package="com.cqkgkj.pojo">
    <class name="Class" table="t_class">
        <!-- id主键自增 -->
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="cname"></property>

        <set name="students" table="t_student">
            <key column="cid"></key>
            <one-to-many class="Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
  • set 标签来配置实体类中的集合属性students
  • name 实体类的属性名
  • table 表名
  • key 外键
  • one-to-many 与集合泛型的实体类对应
<?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.cqkgkj.pojo">
    <class name="Student" table="t_student">
        <!-- id主键自增 -->
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"></property>
        <property name="age"></property>
        
        <many-to-one name="classObj" class="Class" ></many-to-one>
    </class>
</hibernate-mapping>
  • many-to-one 配置实体类对应的对象属性

  • name 属性名

  • class 属性对应的类

  • column 外键

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

<!-- 注册映射文件 -->
<mapping resource="com/cqkgkj/pojo/Student.hbm.xml" />
<mapping resource="com/cqkgkj/pojo/Class.hbm.xml" />

一对多

Hibernate API

import com.cqkgkj.pojo.Class;
import com.cqkgkj.pojo.Student;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class MyTest {
    @Test
    public void test2(){
        //1.加载主配置文件与映射文件
        Configuration configuration = new Configuration().configure();
        //2.创建Session工厂对象
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        //3.开启Session对象
        Session session = sessionFactory.openSession();
        try {
            //4.开启事务
            session.beginTransaction();
            //创建Student
            Student student = new Student();
            student.setAge(22);
            student.setName("张三");
            //创建Class
            Class classObj = new Class();
            classObj.setCname("一班");
            //建立关联关系
            student.setClassObj(classObj);
            //5.执行操作
            session.save(student);
            session.save(classObj);
            //6.提交事务
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            //7.回滚事务
            session.getTransaction().rollback();
        }finally {
            session.close();
        }
    }
}

这里有几个需要注意的点,我在学习的时候遇到的错误:

  • 实体关系映射文件的 的 name 和 的 name 要与实体类里表示关系的对象变量名相同;
  • session.save() 保存数据库是,先保存表示一的对象,在保存表示多的对象,不然外键插入异常。

多对多

配置实体关系映射文件

<?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.cqkgkj.pojo">
    <class name="Account" table="account">
        <!-- id主键自增 -->
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name" ></property>

        <set name="courses" table="account_course">
            <key column="aid" ></key>
            <many-to-many class="Course" column="cid"></many-to-many>
        </set>
    </class>
</hibernate-mapping>
<?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.cqkgkj.pojo">
    <class name="Course" table="course">
        <!-- id主键自增 -->
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name" ></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>

name 实体类对应的集合属性名

table 中间表名

key 外键

many-to-many 与集合泛型的实体类对应

column 属性与中间表的外键字段名对应

注册 Hibernate 配置文件中

<mapping resource="com/cqkgkj/pojo/Account.hbm.xml" />
<mapping resource="com/cqkgkj/pojo/Course.hbm.xml" />

编写测试类代码

import com.cqkgkj.pojo.Account;
import com.cqkgkj.pojo.Course;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

import java.util.HashSet;
import java.util.Set;

public class MyTest {
    @Test
    public void test3(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        try{
            session.beginTransaction();
            Account account = new Account();
            account.setName("张三");
            Course course = new Course();
            course.setName("Java");
            Set<Account> accounts = new HashSet<>();
            accounts.add(account);
            // 设置对应关系
            course.setAccounts(accounts);
            session.save(account);
            session.save(course);
            session.getTransaction().commit();
        } catch (Exception e){
            session.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }
}

Hibernate 延时加载

默认开启

import com.cqkgkj.pojo.Account;
import com.cqkgkj.pojo.Course;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

import java.util.HashSet;
import java.util.Set;

public class MyTest {
    @Test
    public void test4(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        try{
            session.beginTransaction();

            Account account = session.get(Account.class, 2);
            System.out.println(account);

            session.getTransaction().commit();
        } catch (Exception e){
            session.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }
}

查询一张表的数据,当需要查询关联的数据时,才会在另一张表中查询关联数据。

<set name="courses" table="account_course" lazy="false">
	<key column="aid" ></key>
	<many-to-many class="Course" column="cid"></many-to-many>
</set>

在 关联的属性标签中使用标签属性 lazy=“false” 关闭延时加载,则每次查询数据时,其关联的其他表的数据也会一起查出来。

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页