创建多表联查
一对一
public class Teacher{
private int id;
private String name;
private Room room;
}
public class Room{
private int id;
private String name;
private Teacher teacher;
}
配置ORM映射文件
在有外键的一方配置
<class name="Room" table="room">
<id name="id">
<generator class="native"></generator>
</1id>
<property name="name"></property>
<!--
一对一是特虚的多对
name:属性名称
class:属性类型
column:关联本属性的外键字段
-->
<many-to-one name="teacher" class="Teacher" column="t_id" update="true"></many-to-one>
</class>
一对多
/**
创建实体类在一的一方添加set或者list集合,推荐使用set,因为使用的时候需要在集合中添加元素,所以在声明的时候直接进行初始化操作
*/
public class Room{
private int id;
private String name;
private Teacher teacher;
private Set<student> students = new HasSet<>();
}
/**
在一的一方添加另一方的类型属性
*/
public class Student{
private int id;
private String name;
private Room room;
}
一对多
配置ORM映射文件
无论在一的一方还是在多的一方都需要设置外键,所以两边的外键名称
必须一致
<hibernate-mapping package="com.zhiyou.model">
<class name="Room" table="room">
<id name="id">
<genernate class="native"></generator>
</id>
<property name="name"></property>
<!--
name:属性名称
key:关联的外键名称
one-to-many中的class:集合中的元素类型
-->
<set name="students">
<key column="r_id">
<one-to-many class="Student">
</set>
</class>
</hibernate-mapping>
多对多
在两方都定义对方类型的set集合并初始化
public class Student{
private int id;
private String name;
private Set<Course> course = new HashSet<>();
}
public class Course{
private int id;
private String name;
private Set<Student> students = new HashSet<>();
}
配置ORM映射文件
<hibernate-mapping package="com.zhiyou.model">
<class name="Course" table="course">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<!--
name:属性名称
table:多对多关系要生成的第三张表。table为第三张表名
key:当前类型在第三张表中的外键字段名称
many-to-many:多对多,表示另一方的设置内容
class:另一方的类型
column:另一方在第三张表中的字段名称
-->
<set name="students" table="sc_table">
<key column="c_id"></key>
<many-to-many class="Student" column="s_id"/>
</set>
</class>
</hibernate-mapping>
注解
Hibernate提供了Hibernate Annotations扩展包,它可以替换复杂的hbm.xml文件
( Annotations扩展包是hibernate-annotation-3.4.0GA.zip)
使得Hibernate程序的开发大大的简化。利用注解后,可不用定义持久化类型对应的*.hbm.xml,
而直接以注解方式写入持久化类的实现中。
@Entity 将一个类声明为一个持久化类
@Id 声明了持久化类的标识属性(相当于数据表的主键)
@GeneratedValue 定义标识属性值的生成策略
@Table 为持久化类映射指定表(table)
@UniqueConstraint 定义表的唯一约束
@Lob 表示属性将被持久化为Blob或者Clob类型
@Column 将属性映射到列
@Transient 忽略这些字段和属性,不用持久化到数据库。
使用:
- 直接在实体类中添加对应的注解,不需要创建对应的映射文件
- 在hibernate.cfg.xml中通过mapper标签的class属性加载对应的实体类文件
<!--添加映射文件-->
<mapping class="com.zhiyou.modle.Student"/>
<mapping class="com.zhiyou.modle.Room"/>
<mapping class="com.zhiyou.modle.Teacher"/>
<mapping class="com.zhiyou.modle.Course"/>
注解配置对象关联关系(一对一)
@Entity
@Table(name="room")
public class Room{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="name")
private String name;
@OneToOne
@JoinColumn(name="t_id")
private Teacher teacher;
}
//mappedBy表示由teacher对象维护关联
@Entity
@Table(name="teacher")
public class Teacher{
@Id
@GeneratedValue(strategy="GenerationType.IDENTITY")
private int id;
@Column
private String name;
@OneToOne(mappedBy="teacher")
private Room room;
}
配置多对一关系
//JoinColumn指表中表示关联关系的外键字段
@Entity
@Table(name="student")
public class Student{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column
private String name;
@ManyToOne
@JoinColumn(name="r_id")
private Room room;
}
配置一对多关系
@Entity
@Table(name="room")
public class Room{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name="name")
private String name;
@OneToMany(mappedBy="room")
private Set<Student> students
}
注解配置多对多关系
- fetch加载策略 急加载
- joinTable 多对多中第三张表的表名
- joinColumn student表和第三张表外键关联关系
- innerseJoinColumns:course表和第三张表的外键关联关系
@Entity
@Table(name="student")
public class Student{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column
private String name;
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name="sc_table",
joinColumns=@JoinColumn(name="s_id",referencedColumnName="id"),inverseJoinCoumns=@JoinColumn(name="c_id",referencedColumnName="id")
)
private Set<Course> course = new HashSet<>();
}
mappedBy将控制权交给学生(配置的学生类中关联属性名称)
@Entity
@Table(name="course")
public class Course{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column
private String name;
@ManyToMany(mappedBy="courses")
private Set<Student> students = new HashSet<>();
}
mappedBy的作用
mappedBy的意思就是“被映射”,即mappedBy这方不用管关联关系,关联关系交给另一方处理
规律:凡是双向关联,mapped必设,因为根本都没必要在2个表中都存在一个外键关联,在数据库中只要定义一边就可以了 只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性; mappedBy标签一定是定义在the owned side(被拥有方的),他指向the owning side(拥有方);
fetch策略
@OneToMany(fetch=FetchType.EAGER) @Fetch(value=FetchMode.SUBSELECT) 两者都是设定关联对象的加载策略。前者是JPA标准的通用加载策略注解属性。 后者是Hibernate自有加载策略注解属性。
FetchType可选值
FetchType.LAZY: 懒加载,在访问关联对象的时候加载(即从数据库读入内存) FetchType.EAGER:立刻加载,在查询主对象的时候同时加载关联对象。
FetchMode可选值
@Fetch(FetchMode.JOIN): 始终立刻加载,使用外连(outer join)查询的同时加载关联对象,忽略FetchType.LAZY设定。 join对HQL不生效 @Fetch(FetchMode.SELECT) :默认懒加载(除非设定关联属性lazy=false),当访问每一个关联对象时加载该对象,会累计产生N+1条sql语句 @Fetch(FetchMode.SUBSELECT) 默认懒加载(除非设定关联属性lazy=false),在访问第一个关联对象时加载所有的关联对象。会累计产生两条sql语句。且FetchType设定有效