【笔记】Hibernate学习笔记

前言

Hibernate学习笔记

引入依赖

1
2
3
4
5
6
7
8
9
10
<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.7.Final</version>
</dependency>

配置文件

org.hibernate.dialect.MySQLDialectorg.hibernate.dialect.MySQL5Dialectorg.hibernate.dialect.MySQL57Dialect:根据使用的数据库版本进行修改。版本不指定生成的SQL代码量会越多;版本指定越精确生成的SQL代码量越少
com/User.hbm.xml:根据实体类配置子配置文件名。子配置文件与实体类在同级目录下
<property name="hbm2ddl.auto"></property>:配置数据库生成方式

update:表如果存在,就直接插入数据;如果不存在,就创建表
create:每次创建表之前,都会删除原表
create-drop:每次创建表之前,都会删除原表,在关闭会话后,再次删除表
validate:用来验证表结构,如果表不存在或不一致则抛异常

src/main/resources/hibernate.cfg.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernatr-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<!-- 初始化数据库连接 -->
<property name="connection.diver_class">com.mysql.jdbc.url</property>
<property name="connection.url">jdbc:mysql:///数据库名</property>
<property name="connection.username">用户名</property>
<property name="connection.password">密码</property>
<!-- 配置方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 配置数据库生成方式 -->
<property name="hbm2ddl.auto">update</property>
<!-- 指定子配置文件 -->
<mapping resource="com/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>

配置读取配置文件

pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
<build>
<resource>
<directory>src/main/recources</directory>
</resource>
<recource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</recource>
</build>

创建子配置文件

一对一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class User {
private Integer id;
private String name;

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}
}
  • 创建映射配置文件

<hibernate-mapping></hibernate-mapping>:配置映射关系

package="":指定包名,如果不指定,子配置中出现的类名需要用全局限定名

<class></class>:类与表映射配置

name="":指定类名
table="":指定数据表名

<id>:属性与主键字段映射配置

name="":指定属性名
<generator class="native"/>:主键自增策略

<property/>:属性与字段映射配置

name="":指定属性名
column="":指定字段名,如果属性名与字段名一致,可以省略
type="":指定数据类型,如果属性名与字段名一致,可以省略
length="":指定数据长度,可以省略

src/main/resource/com/pojo/User.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernatr-configuration-3.0.dtd">

<hibernate-mapping package="com">
<class name="User" table="user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>

单向多对一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class User {
private Integer id;
private String name;
private Grade grade;

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Grade getGrade() {
return this.grade;
}

public void setGrade(Grade grade) {
this.grade = grade;
}
}

class Grade {
private Integer id;
private String name;

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}
}

<many-to-one/>:指定多对一关系

name="":指定属性名
class="":指定类名
column="":指定字段名,如果属性名与字段名一致,可以省略
foreign-key="":指定外键
not-null="true":指定是否为空

src/main/resource/com/pojo/User.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernatr-configuration-3.0.dtd">

<hibernate-mapping package="com">
<class name="User" table="user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="grade" class="Grade"/>
</class>
</hibernate-mapping>
src/main/resource/com/pojo/Grade.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernatr-configuration-3.0.dtd">

<hibernate-mapping package="com">
<class name="User" table="user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>

单向一对多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class User {
private Integer id;
private String name;

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}
}

class Grade {
private Integer id;
private String name;
private Set<User> users;

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Set<User> getUsers() {
return this.users;
}

public void setGrade(Set<User> users) {
this.users = users;
}
}
src/main/resource/com/pojo/User.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernatr-configuration-3.0.dtd">

<hibernate-mapping package="com">
<class name="User" table="user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>

<set/><set>:指定集合类型

name="":指定集合属性名
<key></key>:指定外键配置

column="":外键列名
foreign-key="":生成的外键约束名,如果省略则随机
not-null="false":是否不允许为空,默认为false

<one-to-many/>:指定一对多关系

class="":指定类名

inverse="":关系维护(只能配置在一的一端,不能配置在多的一端)

false:缺省值,由一的一端维护关系
true:要求多的一端维护关系,一的一端所维护的关系将失效

src/main/resource/com/pojo/Grade.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernatr-configuration-3.0.dtd">

<hibernate-mapping package="com">
<class name="User" table="user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="users">
<key column="user_id"></key>
<one-to-many class="User"/>
</set>
</class>
</hibernate-mapping>

双向一对多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class User {
private Integer id;
private String name;
private Grade grade;

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Grade getGrade() {
return this.grade;
}

public void setGrade(Grade grade) {
this.grade = grade;
}
}

class Grade {
private Integer id;
private String name;
private Set<User> users;

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public Set<User> getUsers() {
return this.users;
}

public void setGrade(Set<User> users) {
this.users = users;
}
}

<many-to-one/>:指定集合类型

cascade="":设置级联,单一的数据被增删改时,其相关的所有数据也执行相同的操作

all:全部级联
save-update:级联插入
create:级联创建
delete:级联删除

src/main/resource/com/pojo/User.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernatr-configuration-3.0.dtd">

<hibernate-mapping package="com">
<class name="User" table="user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="grade" class="Grade"/>
</class>
</hibernate-mapping>

<set/><set>:指定集合类型

cascade="":设置级联,单一的数据被增删改时,其相关的所有数据也执行相同的操作

all:全部级联
save-update:级联插入
create:级联创建
delete:级联删除

src/main/resource/com/pojo/Grade.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernatr-configuration-3.0.dtd">

<hibernate-mapping package="com">
<class name="User" table="user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="users">
<key column="user_id"></key>
<one-to-many class="User"/>
</set>
</class>
</hibernate-mapping>

通过Hibernate操作数据库

  • Hibernate5.x的写法

<filename>:配置文件名,如果省略则默认加载hibernate.cfg.xml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Transaction transaction = null;
try {
// 创建注册服务对象
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure("<filename>").build();
// 从元信息获取会话工厂对象
SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
// 开启事务
transaction = session.beginTransaction();

/* 操作数据库 */

// 提交事务
transcation.commit();
// 关闭会话
session.close();
} catch (Exception e) {
e.printStackTrace();
session.rollback();
} finally {
if (session != null && session.isOpen())
session.close();
}

查询数据

  • 先查询缓存,如果缓存没有,再查询数据库

直接加载

1
User user = session.get(User.class, <num>);

懒加载

  • 执行load()后不会立即加载,只有当对象需要使用时,才会执行查询操作
1
User user = session.load(User.class, <num>);

新增数据

1
2
User user = new User();
session.save(user);

清除缓存

清除全部缓存

1
session.clear();

清除指定缓存

1
session.evict(user);

封装工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class HibernateUtil {
private static ThreadLocal<Session> threadLocal = new ThreadLocal<>();
private static StandardServiceRegistry registry;
private static SessionFactory sessionFactory;

// 初始化会话工厂
static {
registry = new StandardServiceRegistryBuilder().configure().build();
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
}

// 获取会话对象
public static Session getSession() {
Session session = threadLocal.get();
if (null != session || !session.isOpen()) {
if (null != sessionFactory)
buildSessionFactory();
session = (null != sessionFactory) ? sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}

// 加载会话工厂
private static void buildSessionFactory() {
registry = new StandardServiceRegistryBuilder().configure().build();
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
}

// 关闭会话
public static void closeSession() {
Session session = threadLocal.get();
threadLocal.set(null);
if (null != session && session.isOpen())
session.close();
}
}

使用工具类

  • 先查询,后新增/修改/删除
  • 查询不需要开启事务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Session session = null;
Transaction transaction = null;
try {
session = HibernateUtil.getSession();
transaction = session.beginTransaction();

/* 操作数据库 */

transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
} finally {
HibernateUtil.closeSession();
}

对象生命周期

  • 瞬时状态:刚刚使用new语句创建,还没有被持久化。Session中没有,数据库中也没有
  • 持久化状态:已经被持久化,加入到Session的缓存中。Session中有,数据库中也有
  • 游离状态:已经被持久化,但是不处于Session的缓存中。Session中没有,数据库中有

完成

参考文献

哔哩哔哩——bili_206563379