概述
一种对象关系映射(Object Relational Mapping)框架,专注于Java对象与关系型数据库之间的映射,助力开发者实现数据持久化。
参考链接 hibernate框架教程
特点
反射实现
相关对象/概念
org.hibernate.SessionFactory 生成org.hibernate.Session的工厂,数据源代理,多数据源须配备多个工厂
org.hibernate.Session 应用程序和持久化存储介质之间的一个单线程、短周期的轻量级会话对象
持久化对象/集合 与一个session关联,session关闭后失去持久化特性
瞬态(transient)对象/集合 未与session相关联
org.hibernate.connection.ConnectionProvider JDBC 连接的工厂和连接池,应用程序不可用,可被扩展或自定义实现
org.hibernate.TransactionFactory 生成transaction对象的工厂,可扩展或自定义实现
**************************** 项目实例 ****************************
项目结构
![](https://i-blog.csdnimg.cn/blog_migrate/201ca14aa86ffbc1ca0b68dd88ee4f1b.png)
maven 依赖
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.7.Final</version>
</dependency>
设置xml资源文件路径(在pom文件中)
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
user 实体
public class User {
private int id;
private String username;
private String password;
// 省略 setter & getter
}
User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 映射对应的 package -->
<hibernate-mapping package="shiyanlou.test.hibernate.entity">
<class name="User" table="user_info">
<!-- id主键 和其他属性对应表中相应的字段(这些都是在 User.java 实体类中定义的) -->
<id name="id" column="user_id"/>
<property name="username" column="user_username"></property>
<property name="password" column="user_password"></property>
</class>
</hibernate-mapping>
hibernate 配置文件 hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 数据库驱动 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- jdbc 的连接 url 和数据库 -->
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
<!-- 数据库用户名 -->
<property name="connection.username">root</property>
<!-- root用户数据库密码 -->
<property name="connection.password">1234</property>
<!-- <property name="connection.pool_size">1</property>-->
<!-- 数据库方言 (记得查看自己的数据库版本,选择正确的方言)-->
<property name="dialect">org.hibernate.dialect.MySQL57Dialect</property>
<!-- 打印执行的SQL -->
<property name="show_sql">true</property>
<!-- 格式化打印SQL -->
<property name="format_sql">true</property>
<!-- 第一次加载 hibernate 时根据实体类自动建立表结构,以后自动更新表结构 -->
<property name="hbm2ddl.auto">update</property>
<!-- 映射文件 (从java下的包开始,填写正确的路径) -->
<mapping resource="shiyanlou/test/hibernate/entity/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
测试类
public class Test {
public static void main(String[] args) {
// 获取 Hibernate 配置信息
Configuration configuration = new Configuration().configure();
@SuppressWarnings("deprecation")
// 根据 configuration 建立 sessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 开启 session(相当于开启 JDBC 的 connection)
Session session = sessionFactory.openSession();
// 创建并开启事务对象
session.beginTransaction();
// 新建对象,并赋值
User user = new User();
user.setId(1);
user.setUsername("admin");
user.setPassword("admin");
// 保存对象
session.save(user);
// 提交事务
session.getTransaction().commit();
// 关闭 session 和 sessionFactory
session.close();
sessionFactory.close();
}
}
运行这个测试类,或者
注意查看数据库中是否新增一条数据。
** 使用注解代替User.hbm.xml **
@Entity // javax包下
public class User {
@id // javax包下
private int id;
private String username;
private String password;
// 省略 setter & getter
}
**************************** 增删改查 ****************************
新增
session.save(obj)
修改
session.update(obj);
或
session.createQuery("update User set password = ?1 where id = ?2") // 这是 HQL写法,这里使用java类和java属性
.setParameter(1, "123") // ?1 处的参数 如果只有一个参数,可以不写数字,但仍然从1开始
.setParameter(2, 1) // ?2 处的参数
.executeUpdate(); // 执行更新。推荐这种连写方式,从给定HQL,设定参数,到执行一步完成
// .list() // 此处为查询时使用的方法
或
session.createSQLQuery("update user set password = :psd where id = :id") // 原生SQL写法,使用表和列,注意驼峰命名时正确的列名
.setParameter("psd", "123") // 直接使用 语句中的参数名称
.setParameter("id", 1) // 原生SQL也可以使用 ?(问号)传参,规则与HQL相同
.executeUpdate(); // 执行更新
// .list(); // 执行查询
删除
session.delete(obj);
或
session.createQuery("delete from User where id = ?1")
.setParameter(1, 1)
或者使用原生SQL,此处省略
查询
使用HQL查询实体得到的都是该实体对象,此处不再赘述。重点说说原生SQL。
// 这样查询将得到map列表
List<map> mList = session.createSQLQuery(sql)
.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP) // 设定类型转换,此方法已过时
.list();
// 这样查询得到实体列表
List<Employee> list = session.createSQLQuery(sql)
.addEntity(Employee.class) // 设定返回实体类型
.list();
**************************** 映射关系 ****************************
集合映射
在实体对应的 **.hbm.xml文件中
<!-- set集合 -->
<set name="address" table="t_address"> <!-- java属性名,子表表名 -->
<key column="uid"></key> <!-- 外键在字表中的列名 -->
<element column="address" type="string"></element> <!-- 子表中元素的名称,类型 -->
</set>
<!-- list集合 -->
<list name="addressList" table="t_addressList">
<key column="uid"></key>
<list-index column="idx"></list-index> <!-- list序列,指定存储列名 -->
<element column="address" type="string"></element>
</list>
<!-- map集合 -->
<map name="addressMap" table="t_addressMap">
<key column="uid"></key>
<map-key type="string" column="shortName"></map-key> <!-- map键存储列名 -->
<element type="string" column="address"></element>
</map>
一对多
在 “一” 对应的 **.hbm.xml文件中
<set name="users" > <!-- “一”的实体中的属性名,这里表示一组User -->
<key column="group_id" ></key> <!-- 外键名称,将会创建在 user 表中 -->
<one-to-many class="shiyanlou.hibernate.onetomany.entity.User" /> <!-- 表示“多” 的实体-->
</set>
多对一
在 “多” 对应的 **.hbm.xml文件中
<many-to-one name="group" column="group_id"></many-to-one> <!-- “多”的实体中java属性名,在本表中的外键名 -->
!注意,在一对关系中,比如班主任对于该班学生是“一对多”关系,只需要在班主任实体或者学生实体任选一方维护即可。
多对多
在course实体对应的 **.hbm.xml文件中
<set name="students" cascade="save-update" table="sc_table"> <!-- 本实体中的属性名,级联保存,关系表名称 -->
<key column="cou_id" not-null="true"></key> <!-- 在student表中的外键 -->
<many-to-many column="stu_id" class="Student" ></many-to-many> <!-- 在本表中student的外键,student实体类 -->
</set>
在student实体对应的 **.hbm.xml文件中
<!-- 各属性分别是:本实体中的属性名,级联保存,设定反向表(courses)维护关系,关系表名称 -->
<set name="courses" cascade="save-update" inverse="true" table="sc_table">
<!-- column 为中间表参照 student_table 的外键 -->
<key column="stu_id" not-null="true"></key>
<!-- 多对多的关系映射-->
<many-to-many class="Course" column="cou_id"></many-to-many>
</set>
!注意,多对多关系中,应只设定由某一方来维护关系,若双方同时维护,在修改数据时,将会造成死循环事务。