hibernate的配置文件是框架运行的基础,负责定义数据库连接参数、框架核心行为以及实体类和数据库表的映射规则,让开发者无需编写大量原生SQL就能完成对象与关系型数据库的映射和操作。配置文件分为核心配置文件和映射配置文件两类,二者分工不同但共同支撑框架的正常运行。

hibernate配置文件工作原理
hibernate的配置文件整体工作流程可以分为三个核心环节,每个环节都承担着不同的职责。
核心配置文件的作用
核心配置文件通常为hibernate.cfg.xml,主要配置数据库连接相关的参数和框架全局属性。当hibernate启动时,会首先加载该文件,读取其中的配置信息建立数据库连接,同时确定框架的运行规则。
核心配置文件中常见的配置项包括:
- 数据库连接驱动类
- 数据库连接的URL地址
- 数据库用户名和密码
- 数据库方言,用于适配不同数据库的特性
- 是否显示执行的SQL语句
- 是否自动创建或更新数据库表结构
以下是一个标准的核心配置文件示例:
<?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="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/test_db?useSSL=false&serverTimezone=UTC</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<!-- 数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
<!-- 框架行为配置 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 加载映射配置文件 -->
<mapping resource="com/example/entity/User.hbm.xml"/>
<mapping resource="com/example/entity/Order.hbm.xml"/>
<mapping resource="com/example/entity/Course.hbm.xml"/>
</session-factory>
</hibernate-configuration>
映射配置文件的作用
映射配置文件通常为类名.hbm.xml,用于定义单个实体类和数据库表的对应关系,以及实体之间的关联关系。核心配置文件会通过<mapping>标签加载所有需要的映射配置文件,hibernate解析这些文件后就能知道如何将Java对象的属性映射到表的字段,以及如何处理关联数据的增删改查。
整体工作流程
当程序调用Configuration类的configure()方法时,hibernate会加载核心配置文件,然后读取其中配置的所有映射文件。接着框架会根据配置信息创建SessionFactory对象,该对象是线程安全的,整个应用通常只需要创建一个实例。SessionFactory可以创建Session对象,Session是操作数据库的核心接口,开发者通过Session的save、update、delete、get等方法操作实体对象,hibernate会自动将这些操作转换为对应的SQL语句执行,完成数据库操作。
hibernate一对多关联设计
一对多关联是指一个实体对象对应多个另一个实体对象的关系,最典型的场景就是用户和订单的关系,一个用户可以拥有多个订单,而一个订单只属于一个用户。
实体类设计
在用户实体类中需要添加一个订单集合属性,用于存储该用户的所有订单;在订单实体类中需要添加一个用户属性,用于表示该订单所属的用户。
用户实体类代码示例:
package com.example.entity;
import java.util.HashSet;
import java.util.Set;
public class User {
private Integer id;
private String username;
private String password;
// 一对多关联属性,存储该用户的所有订单
private Set<Order> orders = new HashSet<>();
// 省略getter和setter方法
}
订单实体类代码示例:
package com.example.entity;
public class Order {
private Integer id;
private String orderNo;
private Double totalPrice;
// 多对一关联属性,表示该订单所属的用户
private User user;
// 省略getter和setter方法
}
映射配置文件设计
用户类的映射文件中需要使用<set>标签配置一对多关联,订单类的映射文件中需要使用<many-to-one>标签配置多对一关联,二者需要对应。
User.hbm.xml映射文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<!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.example.entity.User" table="t_user">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="username" column="username"/>
<property name="password" column="password"/>
<!-- 一对多关联配置 -->
<set name="orders" cascade="save-update">
<key column="user_id"/>
<one-to-many class="com.example.entity.Order"/>
</set>
</class>
</hibernate-mapping>
Order.hbm.xml映射文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<!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.example.entity.Order" table="t_order">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="orderNo" column="order_no"/>
<property name="totalPrice" column="total_price"/>
<!-- 多对一关联配置 -->
<many-to-one name="user" class="com.example.entity.User" column="user_id"/>
</class>
</hibernate-mapping>
操作示例
配置完成后,就可以通过操作实体对象来维护关联关系,无需手动编写关联表的SQL语句。
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class OneToManyTest {
public static void main(String[] args) {
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
// 创建用户
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
// 创建两个订单
Order order1 = new Order();
order1.setOrderNo("ORD001");
order1.setTotalPrice(199.9);
order1.setUser(user);
Order order2 = new Order();
order2.setOrderNo("ORD002");
order2.setTotalPrice(299.9);
order2.setUser(user);
// 将订单添加到用户的订单集合中
user.getOrders().add(order1);
user.getOrders().add(order2);
// 保存用户,由于配置了级联保存,订单会自动保存
session.save(user);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
hibernate多对多关联设计
多对多关联是指多个实体对象对应多个另一个实体对象的关系,典型场景是学生和课程的关系,一个学生可以选修多门课程,一门课程也可以被多个学生选修。多对多关联需要一张中间表来维护关联关系,中间表至少包含两个字段,分别是两个实体表的主键。
实体类设计
学生实体类中需要添加课程集合属性,课程实体类中需要添加学生集合属性,双方都通过集合来存储对方的关联对象。
学生实体类代码示例:
package com.example.entity;
import java.util.HashSet;
import java.util.Set;
public class Student {
private Integer id;
private String name;
private Integer age;
// 多对多关联属性,存储该学生选修的所有课程
private Set<Course> courses = new HashSet<>();
// 省略getter和setter方法
}
课程实体类代码示例:
package com.example.entity;
import java.util.HashSet;
import java.util.Set;
public class Course {
private Integer id;
private String courseName;
private String teacher;
// 多对多关联属性,存储选修该课程的所有学生
private Set<Student> students = new HashSet<>();
// 省略getter和setter方法
}
映射配置文件设计
双方都使用<set>标签配置多对多关联,并且需要指定中间表的名称,以及双方在中间表中的外键字段。
Student.hbm.xml映射文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<!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.example.entity.Student" table="t_student">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<property name="age" column="age"/>
<!-- 多对多关联配置 -->
<set name="courses" table="t_student_course" cascade="save-update">
<key column="student_id"/>
<many-to-many class="com.example.entity.Course" column="course_id"/>
</set>
</class>
</hibernate-mapping>
Course.hbm.xml映射文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<!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.example.entity.Course" table="t_course">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="courseName" column="course_name"/>
<property name="teacher" column="teacher"/>
<!-- 多对多关联配置 -->
<set name="students" table="t_student_course">
<key column="course_id"/>
<many-to-many class="com.example.entity.Student" column="student_id"/>
</set>
</class>
</hibernate-mapping>
操作示例
多对多关联的操作同样通过维护集合来完成,hibernate会自动维护中间表的数据。
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManyToManyTest {
public static void main(String[] args) {
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
// 创建两门课程
Course course1 = new Course();
course1.setCourseName("Java基础");
course1.setTeacher("李老师");
Course course2 = new Course();
course2.setCourseName("数据库原理");
course2.setTeacher("王老师");
// 创建两个学生
Student student1 = new Student();
student1.setName("张三");
student1.setAge(20);
student1.getCourses().add(course1);
student1.getCourses().add(course2);
Student student2 = new Student();
student2.setName("李四");
student2.setAge(21);
student2.getCourses().add(course1);
// 将学生添加到课程的集合中
course1.getStudents().add(student1);
course1.getStudents().add(student2);
course2.getStudents().add(student1);
// 保存学生,级联保存课程
session.save(student1);
session.save(student2);
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
两种关联设计的注意事项
在设计一对多和多对多关联时,需要注意以下几点:
- 级联属性
cascade的配置需要根据实际业务场景选择,避免不必要的级联操作导致数据误删 - 多对多关联中,双方配置的中间表名称必须一致,外键字段需要和对方配置的主键字段对应
- 集合属性建议使用
Set而不是List,避免关联数据重复 - 如果不需要双向关联,可以只配置单向关联,减少配置复杂度