Hibernate学习笔记
学习途径: 百度搜索”Hibernate注解开发”就可以学到相关的内容
实体类的条件
- @Entity注解
- 一个空参构造器
- 对应的setter、getter方法
操作数据的几种方式
- entityManager.createNativeQuery()创建原生的sql语句操作
- 编写JPQL语句进行操作
- 使用entityManager提供的一些方法进行操作(find、remove、merge)
高级:Panache操作数据库
https://quarkus.io/guides/hibernate-orm-panache
官方文档介绍了使用Panache更方便的操作数据的办法
相关的注解
1 |
|
Cascade级联操作(CascadeType.ALL是全都可以操作,最好不要用)
1 |
|
关系注解(这个搞对了,才能实现返回级联对象,不必手动组装对象返回)
ManyToOne和OneToMany的区别
- 首先!不要去想数据库!不要去想数据库!不要去想数据库!用了Hibernate,所有的表结构,全部用代码就可以表现
- 其次,理清多和一,谁是多,谁是一! 以学生和班级举例,学生是多,班级是一
- 然后,@ManyToOne加在多的一方属性上头,@OnToMany就加在一的那一方的属性头上,一的一方的实体的属性类型肯定是List
(这两个注解作用是相同的,其中一方的实体加就可以了)
@JoinColumn()注解中的name属性写什么?
- name写一的那方的小写+id(比如:banji_id),其实就体现为数据库的外键名
单向和双向
单向关联 :指具有关联关系的实体对象间的加载与访问关系是单向的。即,只有一个实体对象可以加载和访问对方,但对方是看不到另一方的。
双向关联:双向关联是指具有关联关系的实体对象间的加载与访问关系是双向的。即,任何一方均可加载和访问另一方。
Hibernate对象的三种实体状态
Hibernate有三种实体状态,有瞬时态(transiant),持久态(persistent),游离态(detached)。 简单理解就是,瞬时态指的是刚New 新建的一个对象,没有放在Session时,也没有存储在数据库中。 持久态,指这个对象存储在数据库中,并且存在于Session会话中。 而游离态指的是,这个对象存储在数据库中,但已经不存在于Session会话中。
持久化上下文
其实所谓的 Hibernate 持久化上下文指的是 Session 接口或 JPA 的 EntityManager 接口,我们对数据库进行操作都是通过它来实现的。
刚创建的实体类对象的状态是 transient
通过调用 session 的 persist 或 save 方法,实体类对象由 session 管理,它的状态变为了 persistent,此后对该对象的修改操作都会调用 flush 后被同步到数据库中
我们也可以调用 session 的 detach, evict 或 clear 方法把对象移出 session,它的状态变为了 detached,对 detached 对象的操作不会同步到数据库中
如果你想把 detached 对象重新加入到 session 中,我们可以调用 lock, update 或 saveOrUpdate
我们也可以使用 merge 方法把 detached 对象 merge 到 persistent 对象中
我们也可以使用 contains 判断对象是否已经加入 session 中 (persistent 对象)
最后调用 session 的 delete 或 remove 后,它的状态变为 removed
flush 方法用来把对象同步到数据库中
refresh 方法用来把数据库的值同步到对象中
一些注意事项:
- 如果你想要实现级联插入操作,那么在定义实体的时候,对应的一方的外键属性不要设置@Column_(nullable = false),否则你插入的时候会报错,你传来的数据肯定是不含有两个实体id(id都是通过数据库自动生成的),但是由于你设置了nullable=false,所以就报错了。_
EntityManager
在各个Resource类中,都会注入EntityManager对象,该对象执行操作数据库的工作
下面的是JPA的官方文档,里面可以看,列出了相关的方法
https://jakarta.ee/specifications/persistence/3.0/apidocs/allclasses.html
总结增删改查:
- em.persist()
- em.remove()
- em.merge()
- em.find()和em.getReference()
枚举类型映射到数据库
定义实体的时候不加注解
当不使用任何注解的时候,默认情况下是使用
ordinal
属性,也就是Enum类型实例在Enum中声明的顺序来完成映射的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16enum Sex{
FEMALA,
MALA
}
public class Student(){
@Id
@GeneratedValue
private Integer id,
@Column
private String name,
@Column
private String address,
@Column
private Sex sex
}由于使用
ordinal
所以,hibernate在建表的时候,会把Student表里的sex字段定义成int,FAMALE保存成0,MALE保存成1使用
@Enumerated
注解标记对应的字段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
26public enum Gender {
male("男"),
female("女");
private String name;
private Gender(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
//注意,这里的注解类,两个枚举被添加了name属性
public class Student(){
@Id
@GeneratedValue
private Integer id,
@Column
private String name,
@Column
private String address,
@Column
@Enumerated
private Gender gender,
}使用了@Enumerated的注解之后,数据库的字段类型会变成String对应的varchar,而插入数据时,就会变成对应的字符串,如果插入Gender.male;那么数据库里面就是“男”