hibernate里面@mappedBy的作用?

原文:https://www.zhihu.com/question/64187262/answer/217667224

首先,我们整一个Classes和Student,这个很明显了吧,一个班里面有多个学生,然后我们不使用连接表来表示关系,即student表中有一个外键表明这个学生是哪个班的。

@Entity
public class Student {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	private String name;
	@ManyToOne(targetEntity = Classes.class, cascade = CascadeType.ALL)
	@JoinColumn(name = "classesId")
	private Classes classes;
        // 省略了setter、getter这些乱七八糟的东西
}
@Entity
public class Classes {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	private String name;
	@OneToMany(targetEntity=Student.class,cascade=CascadeType.ALL)
	@JoinColumn(name="classesId")
	private Set<Student> students = new HashSet<>();
        // 省略了setter、getter这些乱七八糟的东西 
}

运行下面代码:

Session session = ...;
Transaction tx = session.beginTransaction();

Student s1 = new Student("aaa");
Student s2 = new Student("bbb");
Student s3 = new Student("ccc");
Classes c1 = new Classes("111");
Classes c2 = new Classes("222");

c1.getStudents().add(s1);
c1.getStudents().add(s2);
s3.setClasses(c2);

session.save(c1);
session.save(s3);

tx.commit();
session.close();

生成的表以及里面的数据和我们想的一样:

mysql> desc classes;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255) | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> desc student;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| name      | varchar(255) | YES  |     | NULL    |                |
| classesId | int(11)      | YES  | MUL | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> select * from classes;
+----+------+
| id | name |
+----+------+
|  1 | 111  |
|  2 | 222  |
+----+------+
2 rows in set (0.00 sec)

mysql> select * from student;
+----+------+-----------+
| id | name | classesId |
+----+------+-----------+
|  1 | aaa  |         1 |
|  2 | bbb  |         1 |
|  3 | ccc  |         2 |
+----+------+-----------+
3 rows in set (0.00 sec)

修改Classes类为如下,Student类不变:

@Entity
public class Classes {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	private String name;
	@OneToMany(targetEntity=Student.class,cascade=CascadeType.ALL,mappedBy="classes")
        // 注意没有@JoinColumn
        private Set<Student> students = new HashSet<>();
}

仍然将上面的代码跑一遍。生成的表结构和之前是一样的就不看的,直接看数据:

mysql> select * from classes;
+----+------+
| id | name |
+----+------+
|  1 | 111  |
|  2 | 222  |
+----+------+
2 rows in set (0.00 sec)

mysql> select * from student;
+----+------+-----------+
| id | name | classesId |
+----+------+-----------+
|  1 | aaa  |      NULL |
|  2 | bbb  |      NULL |
|  3 | ccc  |         2 |
+----+------+-----------+
3 rows in set (0.00 sec)

差异还是很明显的,mappedBy="classes"表示一方放弃维护权,并将维护权交给了对方的关联属性classes,这个维护到底是要干些啥?在这里不就是去设置student表中的classesId列的值嘛。看这几行代码:

c1.getStudents().add(s1);
c1.getStudents().add(s2);
s3.setClasses(c2);
session.save(c1);
session.save(s3);

没有mappedBy的时候,大家都要维护,也就是说第四行保存c1的时候,除了要保存c1,s1,s2外,对应的student表中相应记录的classesId的值要被正确的设置,至于是在保存s1和s2的时候设置还是另外使用update语句去设置我这里就不谈了。同样的道理,第五行保存s3的时候,除了保存s3和c2外,对应的student表中相应记录的classesId的值要被正确的设置。

有mappedBy的时候,表示Classes的students 字段放弃维护权,而将维护权交给了Student的关联属性classes。在第四行保存c1的时候,就只保存了c1,s1,s2,由于他放弃了维护权,所以student表中相应记录的classesId的值并没有被正确的设置(也就是上面Student表中的两个NULL)。但是反过来,Student类的classes字段是有维护权的,所以第五行保存s3的时候,除了保存s3和c2外,对应的student表中相应记录的classesId的值要被正确的设置

@OneToOne @OneToMany @ManyToMany 中都有mappedBy属性:
1.一旦指定该属性,则表明当前实体不能控制关联关系
2.当前实体放弃控制关联关系之后,不允许使用 @JoinColumn @JoinTable 修饰代表关联实体的属性

(全文完)

(转载本站文章请注明作者和出处 hibernate里面@mappedBy的作用?