Hibernate笔记之6数据关联一对多
Hibernate数据关联是在Hibernate容器映射技术之上发展起来的。 Hibernate数据关联分为如下三种: 一对一(1:1)一个人拥有唯一身份证号 一对多(1:N)一个部门有很多员工 多对多(M:N)一个学生可以选很多课程,一门课程也可以有多个学生 一对多关系很常见,例如班级与学生的关系就是典型的一对多的关系。在实际编写程序时, 一对多关系有两种实现方式:单向关联和双向关联。 单向的一对多关系只需要在一方进行映射配置,而双向的一对多需要在关联的双方进行映射配置. 下面以Group(班级)和Student(学生)为例讲解如何配置一对多的关系。 单向关联: 单向的一对多关系只需要在一方进行映射配置,所以我们只配置Group的映射文件: <hibernate-mapping> <class name="hibernate.PO.Group" table="t_group" lazy="true"> <id name="id" type="java.lang.Integer"> <column name="id"/> <generator class="increment"/> </id> <!-- insert属性表示被映射的字段是否出现在SQL的INSERT语句中 --> <property name="name" type="java.lang.String" update="true" insert="true"> <column name="name" length="20" /> </property> <!-- set元素描述的字段对应的类型为java.util.Set类型。 inverse用于表示双向关联中的被动一端。inverse的值 为false的一方负责维护关联关系。默认是false。 sort排序关系,其可选值为:unsorted(不排序)。 natural(自然排序)。 comparatorClass(由某个实现了java.util.comparator接口的类型指定排序算法。) <key>子元素的column属性指定关联表(t_student表)的外键。 --> <set name="students" table="t_student" lazy="true" inverse="false" cascade="all" sort="unsorted"> <key column="ID"/> <one-to-many class="hibernate.PO.TStudent"/> </set> </class> </hibernate-mapping> 双向关联: 如果要设置一对多双向关联关系,那么还需要在“多”方的映射文件中使用<many-to-one>标记。 例如,在Group与Student一对多的双向关联中,除了Group的映射文件外还需要在Student的映射文件中加入如下代码: <many-to-one name="group" class="Group" cascade="none" outer-join="auto" update="true" insert="true" column="ID" /> inert和update设定是否对column属性指定的关联字段进行insert和update操作。 也就是说被映射的字段是否出现在SQL的insert或update语句中。 此外将Group.hbm.xml中<set>元素的inverse设置为true. 还是举个实际例子吧: 先是数据库创建脚本: -- 删除表 DROP TABLE person ; DROP TABLE address ; CREATE TABLE person ( pid VARCHAR(32) NOT NULL PRIMARY KEY , name VARCHAR(20) NOT NULL , age INT ) ; CREATE TABLE address ( aid VARCHAR(32) NOT NULL PRIMARY KEY , name VARCHAR(50) NOT NULL , zipcode VARCHAR(10) NOT NULL , pid VARCHAR(32) , FOREIGN KEY (pid) REFERENCES person(pid) ON DELETE CASCADE ) ; ***************************************************************** 然后编写POJO类: package wjr.hibernate.demo23_26.associated1N; import java.util.Set; public class Person { private String pid; private String name; private int age; private Set address; 。。。。。getter和setter方法。。。。 } package wjr.hibernate.demo23_26.associated1N; public class Address { private String aid; private String name; private String zipcode; private String pid; private Person person; 。。。。。getter和setter方法。。。。 } ****************************************************************** 生成和修改配置文件: <class name="wjr.hibernate.demo23_26.associated1N.Person" table="person" catalog="test"> <id name="pid" type="java.lang.String"> <column name="pid" length="32" /> <generator class="uuid.hex"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="20" not-null="true" /> </property> <property name="age" type="java.lang.Integer"> <column name="age" /> </property> <set name="address" inverse="true" cascade="all"> <key> <column name="pid" length="32" unique="true" /> </key> <one-to-many class="wjr.hibernate.demo23_26.associated1N.Address" /> </set><!--inverse="true"表示自动反转关联,也就是在插入数据时能自动将关联id插入数据库, 如果inverse="false",则在插入数据时,先插入,然后再更新关联数据,这样就多了 几条更新语句(插入几条记录就多几条更新语句),效率降低了--> </class> ····················· <class name="wjr.hibernate.demo23_26.associated1N.Address" table="address" catalog="test"> <id name="aid" type="java.lang.String"> <column name="aid" length="32" /> <generator class="uuid.hex"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="50" not-null="true" /> </property> <property name="zipcode" type="java.lang.String"> <column name="zipcode" length="10" not-null="true" /> </property> <many-to-one name="person" class="wjr.hibernate.demo23_26.associated1N.Person" > <column name="pid" length="32" /> </many-to-one> </class> ********************************************************* 编写操作类: package wjr.hibernate.demo23_26.associated1N; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.cfg.Configuration; public class OperateTest { Session session = null; public OperateTest() { session = new Configuration().configure().buildSessionFactory().openSession() ; } public void insert(Person person) { this.session.save(person); this.session.beginTransaction().commit(); } public void update(Person person) { this.session.update(person); this.session.beginTransaction().commit(); } public void delete(String id) { String hql ="delete from Person where pid = ?"; Query q = this.session.createQuery(hql); q.setString(0, id); q.executeUpdate(); this.session.beginTransaction().commit(); } public Person queryByName(String name) { Person p = null; String hql = "FROM Person AS p WHERE p.name=?"; Query q = this.session.createQuery(hql); q.setString(0, name); List all = q.list(); if (all.size() > 0) { p = (Person) all.get(0); } return p; } } ******************************************************************* 最后写测试类: package wjr.hibernate.demo23_26.associated1N; public class TestRun { public static void main(String[] args) { //测试插入 // OperateTest test = new OperateTest(); // Person person = new Person(); // person.setName("wjr"); // person.setAge(25); // //地址 // Address address = new Address(); // address.setName("双流"); // address.setPerson(person); // address.setZipcode("610021"); // // Set set = new TreeSet(); // set.add(address); // person.setAddress(set); // test.insert(person); //测试update OperateTest test = new OperateTest(); Person person = test.queryByName("wjr"); //增加地址 Address address = new Address(); address.setName("人民南路"); address.setPerson(person); address.setZipcode("610041"); person.getAddress().add(address); test.update(person); } } |