常用hibernate注解:表关联,字段属性注解

发布于 2018-07-17  1,956 次阅读


现在主流的的ORM就属hibernate和mybatis了。两者相比之下,hibernate更加灵活,部分SQL功能可以使用丰富的注解实现,而mybatis一般都是构建原生的SQL实现的。


1.基本注解

实现hibernate的核心应该就属Entity。一个简单的JOPO,我们添加@Entity标注这是一个实体类,默认使用类名作为表名,使用字段名作为列明,一个完整的Entity类的结构就对应一张数据库中的表。
我们使用@Table(name="newTableName") 注解自定义表名 使用@Column(name="newColumnName") 注释自定义列明 @Column还可以使用nullbale属性配置是否可空,使用length指定长度。

@Entity
@Table(name = "simple")
@Data
public class simpleTable {
    @Id
    @Column(nullable = false, length = 36)
    private String id;

    @Column(name = "column")
    private String id;
}

这个类最终会被转化为一张表,名字叫simple,里面包含2个varchar类型的列。


2.表关系注解

一张表可能与某张表存在关联,比如classrom和student存在一对多的关系,反过来就是多对一的关系,表也可能是关联自生,一般用于表示一些简单的层级关系。比如公司的组织构架.存在具体某个人身兼多职的情况.那么单个岗位下有多个人,单个人可以又多个岗位。

2.0 一对一关系

针对一对一的情况,比如一个学生对应一张课桌。student作为主控方包含了一个Desk的外键(desk_id),所谓主控方就是能改变关联关系的一方。如下定义,student表在数据库中只存了一个desk的id,但在实体中是具体的Desk类。
@JoinColumn不写会生成一张中间表


public class student() { 
    @OneToOne(cascade=CascadeType.ALL,optional=true)
    //注释本表中指向另一个表的外键。
    @JoinColumn(name="deskId")
    private Desk desk;
}



2.1 一对多关系

针对一对多的情况,我们使用@OneTOMany注解表示,hibernate会自动帮我们设置数据库中的外键。CascadeType用于设置级联属性,比如级联更新 级联删除等。
mappedBy 用在一对多关系中是【一】的一方,其值是存在【多方】的表的列名。在这里会在student类中增加classromno列。
查询某个classrom的时候会自动查询出班级中所有的学生。
当然子表默认都是懒加载模式,没用到的话,是不会自动查询出所有的学生的。

@Entity
@Table(name = "classrom")
@Data
public class ClassRom{
    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "classromno")
    private Set students;
}

2.2 多对一关系

现在我们反过来在学生表上加上多对一的关系注解,使用@ManyToOne表示多对一的关系,CascadeType属性和@OneTOMany中的一样,@JoinColumn设置了一个列用于保存classrom的id,在这里会新增名为classrom_id的列指向对应的classrom。如果不加@JoinColumn则会生成一张中间表,包含了这2张表的id。

@Entity
@Table(name = "student")
@Data
public class Student{
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "classromid")
    private ClassRom classRom;
}

2.3 多对多关系

每个学生都要上多门课程,每门课程又有诺干个学生,这属于多对多的关系。@Id表示这个是id列。@GeneratedValue和@GenericGenerator用于表示这个是hibernate管理的uuid类型的值。
@ManyToMany表示多对多的关系,多对多肯定需要中间表,所以不需要 @JoinColumn和mappedBy

@Entity
@Data
public class Student {
    @Id
    @GeneratedValue(generator = "idGenerator")
    @GenericGenerator(name = "idGenerator", strategy = "uuid")
    private String id;
    private String sName;
    @ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
    private Set courses = new HashSet<>();
}

3.关于DTYPE

假定我定义了个实体People,然后定义了2个子类Student和Teacher。默认设置下,最终在数据库层面只会生成一张people表,people包含了所有资源额外的字段,这个时候我们再从people表读取数据,怎么判断
某一行的数据是应该被实例化成父类还是某个子类的?
这个问题类似于json反序列化时候的多台问题:我该怎么把一个对象序列化成一个接口,或者某个数据可能是某个父类的多个实现类中的任意一个。

hibernate的解决办法和json的解决办法一致,直接标记应该创建成哪个类的实例。在people表中会有个dtype字段,里面存的值是具体的类名,读取的时候直会按类名生成对象。

届ける言葉を今は育ててる
最后更新于 2018-09-07