Hibernate学习笔记_关系映射

    一对一关联                                             

 

一,     一对一单向外键关联

 

a)    Annotation: 在被约束表字段的get方法上加@0ne20ne @JoinColumn

       

//Husband .java
@Entity
public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    
    public String getName() {
        return name;
    }
    @OneToOne
    @JoinColumn(name="wifeId")//指定生成的数据库字段名
    public Wife getWife() {
        return wife;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
    
}

 

 

//Wife .java
@Entity
public class Wife {
    private int id;
    private String name;
    
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
}

 

b)    xml: 在被约束表的xml配置文件中加<many-to-one unique

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.StuIdCard">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="num"/>
        <many-to-one name="student" column="studentId" unique="true"></many-to-one>//unique="true"是保证生成的字段唯一,这样<many-to-one 也达到了一对一的效果
    </class>
    
</hibernate-mapping>

 

二,一对一双向外键关联

 

a)    Annotation: @0ne20ne(mappedBy=”…”)

 

       规律:凡是双向关联,必设mappedBy

 

  在Wife类中 写Husband对象属性 并添加注解@OneToOne(mappedBy="wife") 

mappedBy作用 是指定这个一对一关联是被Husband类的 wife属性(准确说是getWife方法)做的映射

 

//Wife .java
@Entity
public class Wife {
    private int id;
    private String name;
    private Husband husband;
    @OneToOne(mappedBy="wife") //mappedBy作用 是指定这个一对一关联是被Husband类的 wife属性(准确说是getWife方法)做的映射
    public Husband getHusband() {
        return husband;
    }
    public void setHusband(Husband husband) {
        this.husband = husband;
    }
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
}

 

 

       在Husband 类中写Wife对象属性

 

              

@Entity
public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    
    public String getName() {
        return name;
    }
    @OneToOne
    @JoinColumn(name="wifeId")
    public Wife getWife() {
        return wife;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
    
}

 

 

 此注释将由Husband表中生成wifeid字段作为fk外键,wife表中不生成额外的Husbandid字段

 

b)    xml: many-to-one unique     <one-to-one property-ref

 

在Student类中写StuIdCard属性, StuIdCard类中写Student属性

 

StuIdCard.hbm.xml文件中加

 

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.StuIdCard">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="num"/>
        <many-to-one name="student" column="studentId" unique="true"></many-to-one>
    </class>
    
</hibernate-mapping>

 

 

Student.hbm.xml文件中加

 

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Student" dynamic-update="true">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <property name="age" />
        <property name="sex" />
        <property name="good" type="yes_no"></property>
        <one-to-one name="stuIdCard" property-ref="student"></one-to-one>             <!-- property-ref 相当于mappedBy-->
    </class>
    
</hibernate-mapping>

 

 

其中, property-ref 相当于mappedBy

 

此方式生成的StuIdCard表中包含studentid字段作为fk外键, Student表中不生成额外的字段

 

特别说明: 一对一单向外键关联与一对一双向外键关联在数据库的表的格式是一样的,区别在于

 

java程序中. 双向外键关联可通过Hibernate在两个类间互相调用彼此,而单向外键关联只能单方向调用.

三,   一对一单向主键关联(不重要)

b)    @primaryKeyJoinColumn

c)    xml: <one-to-one id 使用 foreign class

四,      一对一双向主键关联(不重要)

b)    @primaryKeyJoinColumn

c)    xml: <one-to-one id 使用foreign class 和 <one-to-one property-ref

 

五,    联合主键

a)    @JoinColumns

Wife类中建立联合主键,建立方式参考 ID生成策略中的联合主键部分

Husband类中写Wife对象属性,并在其get方法上写@OneToOne即可完成一对一外键映射

若想要指定生成的外键名 则需使用@JoinColumns注解,如下:

@Entity
public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    
    public String getName() {
        return name;
    }
/*@JoinColumns用于在一对一外键关联存在联合主键情况时指定生成的外键字段名称

         @JoinColumns的参数为@JoinColumn数组 @JoinColumn内除需指定name属性外还需指定


         referencedColumnName属性值 作用是可指定生成的字段名所对应的目标表字段名*/


    @OneToOne
    @JoinColumns(
        {
            @JoinColumn(name="wifeId", referencedColumnName="id"),
            @JoinColumn(name="wifeName", referencedColumnName="name")
        }
    )
    public Wife getWife() {
        return wife;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
    
}

 

    

@Entity
@IdClass(WifePK.class)
public class Wife {
    private int id;
    private String name;
    private int age;
    
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Id
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Id
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
}

 

public class WifePK implements Serializable {
    private int id;
    private String name;
    
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
}

 

 

     

         组件映射                                                               

1         对象关系:一个对象是另外一个对象的一部分

2         数据库表:一张表

3         annotation:  @Embbeded

       对象模型

Husband(id,name,wife)

Wife(name,age)

Annotation:

在Husband的wife属性上建立注解

@Embedded 表明该对象是从别的位置嵌入过来的,是不需要单独映射的表.

这种方式生成的表为husband(id,name,wifename,wifeage),不会生成wife表.

@Entity
public class Husband {
    private int id;
    private String name;
    private Wife wife;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    
    public String getName() {
        return name;
    }
    @Embedded
    public Wife getWife() {
        return wife;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
    
}

 

 

public class Wife {
    
    private String wifeName;
    private int age;
    
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
        
    public String getWifeName() {
        return wifeName;
    }
    public void setWifeName(String name) {
        this.wifeName = name;
    }
    
}

 

@AttributeOverride注解需要写在getWife方法上,可以重新指定生成的Wife类组件生成的字段名,例如:Husband与Wife两个类中都有name字段,这样在生成表的时候会有冲突,此时采用@AttributeOverride注解可以指定Wife类中的name属性对应新的字段名—“wifename”,

不过@AttributeOverride注解不常用,因为有更好的解决方法. 1:不要在组件的两个映射类中写同名属性;2:如果真的有重复,那么可以在分类中(此处为Wife类)的重复名称的属性上使用如下内容以指定新的字段名:

@Column(name="wifename")

         public String getName() {

                   return name;

          }

 

4         xml: 使用<component,例如:

    

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Husband" >
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <component name="wife">
            <property name="wifeName"></property>
            <property name="age"></property>
        </component>
    </class>
    
</hibernate-mapping>

 

       多对一与一对多                                                         

 

一,        多对一单向关联

实体模型(User多对一Group)

User(id,name,group)多

Group(id,name)一

 

1,    annotaion: @Many2One

只需要在多的一端User属性group进行注解配置

@ManyToOne //多对一关联 User是多的一方 Group是一的一方

@JoinColumn(name="groupid") //指定User表中生成与Group对应的字段名

    public Group getGroup() {

       return group;

}

@Entity
@Table(name="t_user")
public class User {
    private int id;
    private String name;
    private Group group;
    @ManyToOne
    public Group getGroup() {
        return group;
    }
    public void setGroup(Group group) {
        this.group = group;
    }
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

 

@Entity
@Table(name="t_group")
public class Group {
    private int id;
    private String name;
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

2   xml: <many-to-one

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.User" table="t_user">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <many-to-one name="group" column="groupId" />
    </class>
    
</hibernate-mapping>

 

 

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Group" table="t_group">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        
    </class>
    
</hibernate-mapping>

 

标签会在”多”的一端添加外键,相当于在数据库中添加外键

 

二,        一对多单向关联

 

a)   模型(group一对多user)

             Group(id,name,users)一

             User(id,name)多

             设计时在一的这一端存在着多的集合,生成的数据库表通常是在多的一端生成外键.

     Set<User> users = new HashSet<User>();

b)    类:在一的一方存在多方的集合

1,   Annotation:@One2Many

在一的这一端Group端users属性上进行注解配置

@OneToMany //一对多关联 Group是一的一方 User是多的一方

@JoinColumn(name="groupid") //指定User表中生成与Group对应的字段名 注意此处与多对一配置方式不同

Hibernate默认将OneToMany理解为ManyToMany的特殊形式,如果不指定生成的外键列@JoinColumn(name="groupId"),则会默认生成多对多的关系,产生一张中间表。

@Entity
@Table(name="t_group")
public class Group {
    private int id;
    private String name;
    private Set<User> users = new HashSet<User>();
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @OneToMany
    @JoinColumn(name="groupId")
    public Set<User> getUsers() {
        return users;
    }
    public void setUsers(Set<User> users) {
        this.users = users;
    }
}

 

 

@Entity
@Table(name="t_user")
public class User {
    private int id;
    private String name;
    
    
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

 

2,xml 

配置一的那一端Group

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Group" table="t_group">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <set name="users">
            <key column="groupId"></key>
            <one-to-many class="com.bjsxt.hibernate.User"/>
        </set>
    </class>
    
</hibernate-mapping>

 

 

三,         一对多(多对一)双向关联

1,annotation

@Entity
@Table(name="t_group")
public class Group {
    private int id;
    private String name;
    private Set<User> users = new HashSet<User>();
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @OneToMany(mappedBy="group")
    
    public Set<User> getUsers() {
        return users;
    }
    public void setUsers(Set<User> users) {
        this.users = users;
    }
}

 

 

@Entity
@Table(name="t_user")
public class User {
    private int id;
    private String name;
    private Group group;
    @ManyToOne
    public Group getGroup() {
        return group;
    }
    public void setGroup(Group group) {
        this.group = group;
    }
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

 

2,xml

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Group" table="t_group">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <set name="users">
            <key column="groupId"></key>
            <one-to-many class="com.bjsxt.hibernate.User"/>
        </set>
    </class>
    
</hibernate-mapping>

 

 

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.User" table="t_user">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <many-to-one name="group" column="groupId"></many-to-one>
    </class>
    
</hibernate-mapping>

 

 

务必确保在多的一端生成的生成的外键和一的一方生成的外键的名字相同,都为groupId.如果名字不同则会在多的一端生成多余的外键

 

    多对多                                                                                  

一,   单向关联

a)    例如:老师和学生的关系,老师需要知道自己教了哪些学生

b)    数据库:生成中间表

1,   Annotation:@Many2Many

Teacher类中写:(老师知道有哪些学生,学生不知道有哪些老师)

@Entity
public class Teacher {
    private int id;
    private String name;
    private Set<Student> students = new HashSet<Student>();
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @ManyToMany                                             //多对多关联 Teacher是主的一方 Student是附属的一方
    @JoinTable(name="t_s",                      //指定中间表名  
        joinColumns={@JoinColumn(name="teacher_id")},        //本类主键在中间表生成的对应字段
        inverseJoinColumns={@JoinColumn(name="student_id")}  //对方表主键在中间表生成的对应字段
        )
    public Set<Student> getStudents() {
        return students;
    }
    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}

 

 

@Entity
public class Student {
    private int id;
    private String name;
    
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

 

2,  xml

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Teacher">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <set name="students" table="t_s">
            <key column="teacher_id"></key>
            <many-to-many class="com.bjsxt.hibernate.Student" column="student_id"/>
        </set>
    </class>
    
</hibernate-mapping>

 

 

二,  双向关联

a)    老师知道自己教了哪些学生,学生也知道教自己的有哪些老师

b)    数据库:生成中间表

1,    Annotation:

@Entity
public class Teacher {
    private int id;
    private String name;
    private Set<Student> students = new HashSet<Student>();
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @ManyToMany
    @JoinTable(name="t_s",
        joinColumns={@JoinColumn(name="teacher_id")},
        inverseJoinColumns={@JoinColumn(name="student_id")}
        )
    public Set<Student> getStudents() {
        return students;
    }
    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}

 

 

@Entity
public class Student {
    private int id;
    private String name;
    private Set<Teacher> teachers = new HashSet<Teacher>();
    @ManyToMany(mappedBy="students")
    public Set<Teacher> getTeachers() {
        return teachers;
    }
    public void setTeachers(Set<Teacher> teachers) {
        this.teachers = teachers;
    }
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

2,  xml

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Teacher">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <set name="students" table="t_s">
            <key column="teacher_id"></key>
            <many-to-many class="com.bjsxt.hibernate.Student" column="student_id"/>
        </set>
    </class>
    
</hibernate-mapping>

 

 

<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Student">
        <id name="id">
            <generator class="native"></generator>
        </id>
        
        <property name="name"></property>
        <set name="teachers" table="t_s">
            <key column="student_id"></key>
            <many-to-many class="com.bjsxt.hibernate.Teacher" column="teacher_id"/>
        </set>
    </class>
    
</hibernate-mapping>

 

posted @ 2014-12-04 15:14  enjoy_clh  阅读(246)  评论(0编辑  收藏  举报