hibernate中的组件映射

组件映射

1 项目:hibernate_1100_component

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

3 数据库表:一张表

4 annotation: @ Embeddable @Embbeded

对象模型

Husband(id,name,wife)

Wife(name,age)

Annotation:

在Husband的wife属性上建立注解

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

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

@AttributeOverride注解需要写在getWife方法上,可以重新指定生成的Wife类组件生成的字段名,例如:Husband与Wife两个类中都有name字段,这样在生成表的时候会有冲突,此时采用@AttributeOverride注解可以指定Wife类中的name属性对应新的字段名—“wifename”,不过@AttributeOverride注解不常用,因为有更好的解决方法. 1:不要在组件的两个映射类中写同名属性;2:如果真的有重复,那么可以在分类中(此处为Wife类)的重复名称的属性上使用如下内容以指定新的字段名:

@Column(name="wifename")

public String getName() {

return name;

}

另外,@ Embeddable注解好像是写在分类(Wife类)的类名前的,不过好像不写也行

@Embeddable

public class Wife {… …}

5         xml: 使用<component,例如:

<class name="Husband" >

<id name="id">

<generator class="native"/>

</id>

<property name="name"></property>

<component name="wife">

<property name="wifeName"/>

<property name="wifeAge"/>

</component>

</class>

多对一与一对多

1 多对一单向关联

   a)项目名称:hibernate_1200_many2one_uni

实体模型(User多对一Group)

User(id,name,group)多

Group(id,name)一

  b)数据库表设计:在多方加外键

错误做法:在一方加冗余


perosnid


person name


dreamid


1


zhangsan


1


1


zhangsan


2


dreamid


dreamdescr


1


earn money


2


eat a lot

  c)annotaion: @Many2One

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

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

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

      public Group getGroup() {

        return group;

    }

  d)xml: <many-to-one

  <many-to-one name="group" column="groupId" />

  标签会在”多”的一端添加外键,相当于在数据库中添加外键生成的表为user(id,name,groupid),t_group(id,groupname)

属性cascade

<many-to-one name="group" column="groupid" cascade="all"/>

取值all,none,save-update,delete,对象间的级联操作,只对增删改起作用.

在存储时User时,设置了cascade="all"会自动存储相应的t_group.而不用管user关联的对象(通常情况下会优先存储关联的对象,然后再存储user)

2 一对多单向关联

  a) 项目名称:hibernate_1300_one2many_uni

模型(group一对多user)

Group(id,name,users)一

User(id,name)多

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

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

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

  c) 数据库表同上

  d)Annotation:@One2Many

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

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

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

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

    e)xml:<set <one2many

    XML配置中配置一的那一端Group

    <class name="com.hibernate.Group" table="t_group">

<id name="id">

<generator class="native"/>

</id>

<property name="name"/>

<set name="users">

<key column="groupId"/>指定生成外键字段的名字

<one-to-many class="com.pojo.User"/>

</set>

    </class>

3 一对多(多对一)双向关联

一对多与多对一的双向关联是同一种情况.

关系模型(group一对多user)

Group(id,name,users)一

User(id,name,group)多

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

配置规则:一般以多的一端为主,先配置多的一端

在多的一端User端配置group

@ManyToOne

@JoinColumn(name="groupid")

在一的一端Group端配置时,在users只需要加个mappedBy="groupid"

@OneToMany(mappedBy="group")

XML配置

Group中

<set name="users">

<key column="groupId"/>

<one-to-many class="com.hibernate.User"/>

</set>

在User中

<many-to-one name="group" column="groupId"/>

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

如果名字不同则会在多的一端生成多余的外键

多对多

1 单向关联:

  a) 项目:hibernate_1500_many2many_uni

关系模型(Teache多对多Student),从Teacher这一端能关联到students.

Teacher(id,name,students)多

Student(id,name)多

Set<Student> students=new HashSet<Student>()

在Teacher那一端配置

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

  c)数据库:生成中间表

  d)Annotation:@Many2Many

Teacher类中写:

private Set<Student> students = new HashSet<Student>();

@ManyToMany //多对多关联 Teacher是主的一方 Student是附属的一方

@JoinTable(name="t_s", //指定中间表表名

joinColumns={@JoinColumn(name="teacherid")},//本类主键在中间表生成的

对应字段名

inverseJoinColumns={@JoinColumn(name="studentid")}//对方类主键在中间表

生成的对应字段名

)

public Set<Student> getStudents(){……}

  e)XML:<many2many

<class name="com.xxx.Teacher">

<id name="id">

<generator class="native"/>

</id>

<property name="name"/>

<set name="students" table="t_s">table定义中间表的表名

<key column="teacher_id"></key>

<many-to-many class="com.xxx.Student" column="student_id"/>

</set>

</class>

  2 双向关联:

    a)项目:hibernate_1600_many2many_bi

    多对多双向配置只需要在两端类进行配置就才可以.

  关系模型(Teache多对多Student)

   Teacher(id,name,students)多

    Student(id,name,teachers)多

    Set<Student> students = new HashSet<Student>()

    Set<Teacher> teachers = new HashSet<Teacher>();

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

  c)数据库:生成中间表

  d) Annotation:

  在Teacher这一端的students上配置

    @ManyToMany

     @JoinTable(name="t_s",

     joinColumns={@JoinColumn(name="teacher_id")},

     inverseJoinColumns={@JoinColumn(name="student_id")}

   )

  在Student一端的teachers只需要配置

    @ManyToMany(mappedBy="students")

    注意:mappedBy 与 @JoinTable等一类的配置要分开,不然表字段可能乱

  e)XML:

  XML配置方式:两端配置一样,注意表名和生成的中间表的字段属性名要一致

Teacher那一端配置

<set name="students" table="t_s">

<key column="teacher_id"/>

<many-to-many class="com.xxx.Student" column="student_id"/>

</set>

在Student那一端配置

<set name="teachers" table="t_s">

<key column="student_id"></key>

<many-to-many class="com.xxx.Teacher" column="teacher_id"/>

</set>

生成的数据库表和上面是一样的

关联关系中的CRUD_Cascade_Fetch

1         hibernate_1700_one2many_many2one_bi_crud

2         设定cascade以设定在持久化时对于关联对象的操作(CUD,R归Fetch管)

3         cascade仅仅是帮我们省了编程的麻烦而已,不要把它的作用看的太大

a)    Cascade的属性是数组格式,指明做什么操作的时候关联对象是绑在一起的

b)    refresh = A里面需要读B改过之后的数据

cascade={CascadeType.ALL}

CascadeType取值

ALL    Cascade all operations所有情况

MERGE  Cascade merge operation合并(merge=save+update)

PERSIST  Cascade persist operation存储 persist()

REFRESH  Cascade refresh operation刷新

REMOVE   Cascade remove operation删除

4  铁律:双向关系在程序中要设定双向关联

5  铁律:双向mappedBy

6  fetch

  a) 铁律:双向不要两边设置Eager(会有多余的査询语句发出)

  b) 对多方设置fetch的时候要谨慎,结合具体应用,一般用Lazy不用eager,特殊情况(多方数量不多的时候可以考虑,提高效率的时候可以考虑)

  @OneToMany(mappedBy="group",

  cascade={CascadeType.ALL}, //控制增删改(即CUD)

  fetch=FetchType.EAGER //控制查询(即R) EAGER值代表取出关联 LAZY值为不取关联

//多的一方fetch取值默认为LAZY 一的一方默认为EAGER

)

另外:如果User类(即多的一方)中设置fetch=FetchType.LAZY 则在调用多(即Group)的对象值的时候

类似延迟加载 即需要在commit();之前 session还存在时调用 如:

System.out.println(user.getGroup().getName());

session.getTransaction().commit();

7 Update时@ManyToOne()中的cascade参数关系

session.beginTransaction();

User user = (User)session.load(User.class,1);

//user对象属性改变 事务commit时自动判断与数据库原有数据不同 可自动update

//此时的update与@ManyToOne()中的cascade或fetch参数取值无关

user.setName("user1");

user.getGroup().setName("group1");

session.getTransaction().commit();

如果user改变在commit()之后 且想要执行Update方法时 user与group表同时更新则,则User类的cascade={CascadeType.ALL},并在程序中写如下代码:

session.beginTransaction();

User user = (User)session.get(User.class,1);

session.getTransaction().commit();

user.setName("user1");

user.getGroup().setName("group1");

Session session2 = sessionFactory.getCurrentSession();

session2.beginTransaction();

session2.update(user);

session2.getTransaction().commit();

8         Delete时@ManyToOne()中的cascade关系

如果User及Group类中均设为@ManyToOne(cascade={CascadeType.All}),那么在执行如下:

session.beginTransaction();

User user = (User)session.load(User.class,1);

session.delete(user);

session.getTransaction().commit();

注意:此处删除的是 多对一(即User对Group) 中的“多”的一方(User类)

会删除user及user对应的group,再反向对应group的user都会删除,原因就是设置了@ManyToOne(cascade={CascadeType.All})

三种方法可避免全部删除的情况:

1.  去掉@ManyToOne(cascade={CascadeType.All})设置;

2.  直接写Hql语句执行删除;

3.  将user对象的group属性设为null,相当于打断User与Group间的关联,代码如下

session.beginTransaction();

User user = (User)session.load(User.class,1);

user.setGroup(null);

session.delete(user);

session.getTransaction().commit();

注意:如果删除的是 多对一中的“一”的一方(Group类)时,如果使用第3种方式(user属性设为null)来打断两个对象间的关联的话,代码与之前不同,如下:

session.beginTransaction();

Group group = (Group)session.load(Group.class,1);

//循环将group中的set集合下的各个user对象设为null

//相当于先将数据库中user表中与group表关联的字段(即groupid)设为null

for(User user :group.getUsers()){

System.out.println(user.getName());

user.setGroup(null);

}

//再将group的set集合设为null,相当于将group表中与user表关联的字段(即userid)设为null

//此句的前提是user表中的关联字段(groupid)已经为null,如没有则相当于破坏了一对多关联,会报错

group.setUsers(null);

session.delete(group);

session.getTransaction().commit();

9         O/RMapping 编程模型

a)    映射模型

  1. i.      jpa annotation(java提供的annotation配置--常用)
  2. ii.     hibernate annotation extension(Hibernate扩展的annotation配置--较少用)
  3. iii.     hibernate xml(Hibernate的xml配置方式--常用)
  4. iv.     jpa xml(java提供的xml配置--较少用)

b)    编程接口

  1. i. Jpa(不常用)
  2. ii. hibernate(现在用)

c)    数据査询语言

  1. i. HQL
  2. ii. EJBQL(JPQL)

10     要想删除或者更新先做load,除了精确知道ID之外

11     如果想消除关联关系,先设定关系为null.再删除对应记录,如果不删记录,该记录变成垃圾数据

12     练习:多对多的CRUD


teacher


student


t1


s1


t1


s2


t2


s1


t2


s2

时间: 2024-10-15 21:07:10

hibernate中的组件映射的相关文章

Hibernate中的一对一映射关系

Hibernate中的一对一映射关系有两种实现方法(一对一关系:例如一个department只能有一个manager) I使用外键的方式 步骤:1在一对一关联的持久化类中互相添加对方对象属性,   例如在department中添加private manager manager属性:   department代码如下: package com.atguigu.hibernate.one2one.foreign; public class Department { private Integer d

Hibernate中一对一关联映射/组件映射

Hibernate映射:一对一关联 1.按照外键映射 2.按照主键映射 组件映射 下面以员工账号表和员工档案表(员工账号和档案表之间是一对一的关系)为例,介绍这两种映射关系,并使用这两种 映射方式分别完成以下持久化操作 (1)保存员工档案的同时分配给员工一个账号 (2)加载员工档案的同时加载账号信息 一:按照外键映射

Hibernate中的继承映射

1.继承映射 继承映射分为两种情况:简单继承映射和继承映射. 在简单继承映射中,每个子类都要写一个映射文件. 在继承映射中,只使用一个映射文件.继承映射分为三种情况: 所有子类映射到一张表 需要使用鉴别器字段,不符合数据库设计原则 每个类映射到一张表 父类映射到一张表,插入一条子类信息,需要两条sql,父子表之间有外键约束 每个类映射到一张表,父类不映射表 必须使用uuid作为主键类型,所以bean中主键对应的属性不能是int类型 2.简单继承映射 <?xml version="1.0&q

hibernate中使用组件作为标识符

在数据库设计的时候,有时候难免会将主键设置为联合主键(即唯一标识某一实体的属性不止一个).那么在hibernate中将怎么处理组件作为主键呢? 首先创建一个组件类,以Student为例,如果你想将学生的ID和Name作为联合主键,那么你的组件类应该这样写: 1 import java.io.Serializable; 2 3 @SuppressWarnings("serial") 4 //组件类必须实现Serializable接口,并且要重写equals和hashcode方法 5 //

hibernate中Set集合映射

set集合映射三要素(从javabean映射到数据 ORM)) 1,集合表(外键表,子表)名称 2.,指定集合表外键<key column=""> 3.集合表其他元素<element type="" column=""> <set name="addressSet" table="user_addressSet" order-by="address ASC"

hibernate中多表映射关系配置

1.one-to-many一对多关系的映射配置(在一的一方实体映射文件中配置) <!-- cascade属性:级联操作属性 save-update: 级联保存,保存客户时,级联保存客户关联的联系人 delete:级联删除,删除客户时,级联删除客户关联的联系人 all:级联保存+级联删除 --> <!-- inverse属性:设置是否不维护关联关系 true:不维护关联 false(默认值):维护关联 --> <!-- 一对多 --> <set name="

菜鸟学习Hibernate——一对多关系映射

Hibernate中的关系映射,最常见的关系映射之一就是一对多关系映射例如学生与班级的关系,一个班级对应多个学生.如图: Hibernate中如何来映射这两个的关系呢? 下面就为大家讲解一下: 1.创建实体类Classes和实体类Student Classes.java package com.bjpowernode.hibernate; import java.util.Set; public class Classes { private int id; private String nam

Hibernate之组件映射

1:为什么要使用组件映射 答:建立关系数据模型的一个重要原则是在不会导致数据冗余的前提下,尽可能减少数据库表的数目及表之间的外键参照关系.以员工信息为例,员工信息中有员工的家庭地址信息,如果把地址信息单独放在一张表中,然后建立员工信息表和地址信息表之间的外键参照关系,当每次查询员工信息时,都需建立者两个表的连接.建立表的连接是很耗时的操作,为了提高数据库运行性能,可以把这两张表的信息整合在一张员工信息表EMPINFO中. 2:什么是组件映射:组件是一个被包含的对象,它和它的所有者同存于一张表中,

hibernate中的映射文件xxx.hbm.xml详解总结

转自 http://blog.csdn.net/a9529lty/article/details/6454924 一.hibernate映射文件的作用: Hibernate映射文件是Hibernate与数据库进行持久化的桥梁   二,Hibernate映射文件主要内容:     (1).映射内容的定义: Hibernate映射文件由<hibernate-mapping package="JavaBean所在包的全路径">节点定义映射内容并指定所对应的JavaBean的位置(