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>
时间: 2024-10-12 04:37:13

Hibernate学习笔记_关系映射的相关文章

Hibernate学习笔记_关系映射_其他

集合映射(不太重要) 1         Set 2        List (与Set差不多 多个@OrderBy) a) @OrderBy     排序 private List<User> users = new ArrayList<User>(); @OneToMany(mappedBy="group", cascade={CascadeType.ALL} ) @OrderBy("name ASC") public List<U

Hibernate学习笔记_关系映射_树状结构练习

1         树状结构的设计(至关重要) a) 在同—个类中使用One2Many和Many20ne @Entity public class Org { private int id; private String name; private Set<Org> children=new HashSet<Org>(); private Org parent; @Id @GeneratedValue public int getId() { return id; } public

hibernate学习四(关系映射一对一)

一.关系映射简介 在数据库中,表与表的关系,仅有外键.但使用hibernate后,为面向对象的编程,对象与对象的关系多样化:如 一对一,一对多,多对多,并具有单向和双向之分. 开始练习前,复制上一次项目,并更名为 二.一对一单向外键关联 例如:一个老师只教一个学生,一个学生只能被一个老师教 关系图如: 修改teahcer.java和student.java类(为了简单起见吧Student也更改为使用Annotation的形式) 1 package com.model; 2 3 import ja

Hibernate学习笔记_查询

HQL vs EJBQL 1         NativeSQL >HQL.> EJBQL(JPQL 1.0) > QBC(Query By Criteria) > QBE(Query By Example)" 2         总结:QL应该和导航关系结合,共同为査询提供服务. @Test public void testHQL_01() { Session session = sf.openSession(); session.beginTransaction();

hibernate学习笔记_基础配置

一.hibernate.cfg.xml: hbni2ddl.auto 二.搭建日志环境并配置显示DDL语句 我们使用slf接口,然后使用log4j的实现. 1.  首先引入log4j的jar包(log4j-1.2.14.jar), 2.  然后再引入slf4j实现LOG4J和适配器jar包(slf4j-log4j12-1.5.8.jar) 3.  最后创建log4j的配置文件(log4j.properties),并加以修改,只要保留 log4j.logger.org.hibernate.tool

Hibernate学习笔记_事务

 事务并发处理(面试的意义更大)                        a)   事务:ACID i.   Atomic(原子性) Consistency(一致性) Isolation(隔离性) Durability(独立性) b)   事务并发时可能出现的问题: 第一类丢失更新(Lost Update) 时间 取款事务A 存款事务B T1 开始事务   T2   开始事务 T3 查询账户余额为1000元   T4   查询账户余额为1000元 T5   汇入100元把余额改为1100元

Hibernate学习笔记_缓存

一级缓存和二级缓存和査询缓存(面试题)                 a)    什么是缓存 b)    什么是一级缓存,session级别的缓存 c)    什么是二级缓存,SessionFactory级别的缓存,可以跨越session存在 i.   经常被访间 ii.   改动不大不会经常改动 iii.   数重有限 d)    打开二级缓存 i.   hibernate.cfg.xml 设定: <property name= "cache.use_second_level_cach

Hibernate学习笔记_联合主键

复合主键(联合主键):多个字段构成唯一性. 一,xml方式 1. 将联合主键的属性提取出来,重新编写一个StudentPK类(原Student类中的id,name要删除 并新加入属性“StudentPK”) //StudentPK .javapackage com.bjsxt.hibernate; public class StudentPK implements java.io.Serializable{ private int id; private String name; public

Hibernate学习笔记_性能优化

注意session.clear()的运用,尤其在不断分页循环的时候 a)    在一个大集合中进行遍历,遍历msg,取出其中的含有敏感字样的对象 b)    另外一种形式的内存泄露  (  //面试题:Java有内存泄漏吗?语法级别没有 但是可由java引起,例如:连接池不关闭,或io读取后不关闭) 1+N问题 (典型的面试题)                                              a)    @ManyToOne(fetch=FetchType.LAZY)