Hibernate学习笔记 -- day08 注解含义、一对多关系映射

来源:互联网 发布:html5个人网站源码 编辑:程序博客网 时间:2024/05/16 00:43

一、表关系原则

1、对象关系映射(ORM)建立表关系映射应遵循以下步骤

第一步:明确两张表之间的关系

第二步:在数据库中建立两张表之间的关系

第三步:在实体类中描述出两个实体之间的关系

第四步:在映射配置(注解/XML)中建立两个实体之间的关系

二、表关系映射中注解含义


三、一对多关联关系示例

1、以客户的联系人为例

四、明确关系

1、一家公司可以包含多个员工,多个员工可能属于同一家公司

五、数据库中建立表关系

1、一对多表关系,在数据库中靠的是外键约束。 

2、我们习惯把一对多中一的方称之为:主表。把多的一方称之为:从表。

3、外键:

      指的是从表中有一列,它的取值来源于主表的主键。

      我们就把从表中的这一列叫外键。

六、实体类中描述出两个实体之间的关系

1、主表实体中包含的是从表实体的一个集合引用,集合的元素都是从表的实体。

/** * 客户的实体 * @author zhy * 注解都是JPA规范的 */@Entity@Table(name="cst_customer")public class Customer implements Serializable {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column(name="cust_id")private Long custId;@Column(name="cust_name")private String custName;@Column(name="cust_source")private String custSource;@Column(name="cust_industry")private String custIndustry;@Column(name="cust_level")private String custLevel;@Column(name="cust_address")private String custAddress;@Column(name="cust_phone")private String custPhone;//一对多关系映射:一个客户可以包含多个联系人 @OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.REMOVE) private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);

2、从表实体中包含的是主表实体的一个对象引用。

/** * 联系人的实体 * @author zhy * */@Entity@Table(name="cst_linkman")public class LinkMan implements Serializable {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column(name="lkm_id")private Long lkmId;@Column(name="lkm_name")private String lkmName;@Column(name="lkm_gender")private String lkmGender;@Column(name="lkm_phone")private String lkmPhone;@Column(name="lkm_mobile")private String lkmMobile;@Column(name="lkm_email")private String lkmEmail;@Column(name="lkm_position")private String lkmPosition;@Column(name="lkm_memo")private String lkmMemo;//多对一关系映射:多个联系人对应一个客户@ManyToOne(targetEntity=Customer.class)@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")private Customer customer;

七、在配置映射中体现两个实体之间的关系

1、注解的方式配置关联关系

客户实体

//一对多关系映射:一个客户可以包含多个联系人 @OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.REMOVE) private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);

联系人实体

//多对一关系映射:多个联系人对应一个客户@ManyToOne(targetEntity=Customer.class)    //参数:1、从表中外间字段的名称,2、主表的主键@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")private Customer customer;

2、xml方式配置关联关系

客户映射文件

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.itcast.domain"><!-- package用于导入一个包,接下来再配置文件中再出现此包的类都可以不用导了。 --><class name="Customer" table="cst_customer"><id name="custId" column="cust_id"><generator class="native"></generator></id><property name="custName" column="cust_name"></property><property name="custSource" column="cust_source"></property><property name="custIndustry" column="cust_industry"></property><property name="custLevel" column="cust_level"></property><property name="custAddress" column="cust_address"></property><property name="custPhone" column="cust_phone"></property><!-- 一对多关系映射 涉及的标签set:用于映射set集合属性属性:  name:指定集合属性的名称  table:在一对多的时候写不写都可以。  它指定的是集合元素所对应的表one-to-many:用于指定当前映射配置文件所对应的实体和集合元素所对应的实体是一对多关系。属性:   class:指定集合元素所对应的实体类名称。key:用于映射外键字段的。属性:   column:指定从表中的外键字段名称--><set name="linkmans" table="cst_linkman"><key column="lkm_custid"></key><one-to-many class="LinkMan"/></set></class></hibernate-mapping>

联系人映射文件

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.itcast.domain"><class name="LinkMan" table="cst_linkman"><id name="lkmId" column="lkm_id"><generator class="native"></generator></id><property name="lkmName" column="lkm_name"></property><property name="lkmGender" column="lkm_gender"></property><property name="lkmPhone" column="lkm_phone"></property><property name="lkmMobile" column="lkm_mobile"></property><property name="lkmEmail" column="lkm_email"></property><property name="lkmPosition" column="lkm_position"></property><property name="lkmMemo" column="lkm_memo"></property><!-- 多对一关系映射 涉及的标签:many-to-one:用于建立多对一的关系映射配置属性:  name:指定的实体类中属性的名称  class:该属性所对应的实体类名称。如果在hibernate-mapping上没有导包,则需要写全限定类名  column:指定从表中的外键字段名称--><many-to-one name="customer" class="Customer" column="lkm_cust_id"></many-to-one></class></hibernate-mapping>

八、一对多关系的操作

1、保存

注意:明确主表和从表保存顺序不同产生的不同结果

/** * 保存操作 * 需求: * 1、创建一个客户,创建一个联系人 * 2、建立客户和联系人的双向关联关系 * 3、保存客户和联系人 * 问题: * 我们先保存谁呢? *  测试: *  我们先保存的联系人(从表),再保存主表。 *  会产生3条SQL语句。其中有两条insert,一条update。 *  我们明明只需要两条insert。 *  原因: *  快照机制 *  保存原则: *  先保存主表实体,再保存从表实体 *  */@Testpublic void test1(){//准备数据Customer c = new Customer();c.setCustName("TBD云集中心");c.setCustIndustry("商业办公");c.setCustLevel("VIP客户");c.setCustSource("电话");c.setCustAddress("昌平区北七家");c.setCustPhone("010-34343548");LinkMan l = new LinkMan();l.setLkmName("TBD联系人");l.setLkmGender("male");l.setLkmMobile("13811111111");l.setLkmPhone("010-34593498");l.setLkmPosition("商务部员工");l.setLkmEmail("3293498@qq.com");l.setLkmMemo("普通员工");//建立双向关联关系c.getLinkmans().add(l); l.setCustomer(c);Session s = HibernateUtil.getCurrentSession();Transaction tx = s.beginTransaction();//保存操作//s.save(l);//联系人实体状态转变:变成持久态联系人的快照产生了:关联的客户OID是null//s.save(c);//客户实体状态转变:变成持久态s.save(c);Customer c1 = s.get(Customer.class, c.getCustId());System.out.println(c1);s.save(l);tx.commit();}

2、更新操作

注意:想要在更新主表的时候级联保存(更新)从表,需要在实体类上加上级联操作的注解:cascade

//一对多关系映射:一个客户可以包含多个联系人 @OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.REMOVE) private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);

/** * 更新操作 * 需求: * 1、根据id查询一个客户 * 2、创建一个新的联系人 *  3、为查询出来的客户分配新的联系人(建立联系人和客户的关联关系) *  4、更新客户 * 问题: * 当我们更新时,不会有任何更新的操作。新创建的联系人没有给客户分配成功。 * 解决: * 使用配置的方式,告知Hiernate框架,为我们进行级联操作。 * 告知的方式: * 在注解上使用注解的属性。 */@Testpublic void test2(){//准备数据LinkMan l = new LinkMan();//瞬时态对象l.setLkmName("TBD联系人test3");l.setLkmGender("male");l.setLkmMobile("13811111111");l.setLkmPhone("010-34593498");l.setLkmPosition("商务部员工");l.setLkmEmail("3293498@qq.com");l.setLkmMemo("普通员工");Session s = HibernateUtil.getCurrentSession();Transaction tx = s.beginTransaction();//根据id查询客户Customer c1 = s.get(Customer.class, 1L);//建立客户和联系人的关联关系c1.getLinkmans().add(l);//联系人是瞬时态l.setCustomer(c1);//联系人是瞬时态//更新客户s.update(c1);//我们希望的是在此行,hibernate框架能帮我们做两件事。(先把临时态对象转成持久态,然后再去更新)tx.commit();}

3、删除操作

/** * 删除操作: * 删除从表数据: * 随便删。 *  删除主表数据: *  需要看看有没有从表的引用: *  有从表引用: *  一般情况下不能删。 *  要想删除的话:需要使用级联删除。 *  它的作用就是:先把从表的数据删了,再删除主表数据。 *  实际开发中一定要慎用! *  没有从表引用: *  随便删 */@Testpublic void test3(){Session s = HibernateUtil.getCurrentSession();Transaction tx = s.beginTransaction();//根据id查询客户Customer c1 = s.get(Customer.class, 1L);//删除id为1的客户s.delete(c1);tx.commit();}


阅读全文
0 0