RSS

映射多对一,一对多关联关系

03 Apr

多对一单向关联

1. 表与表之间的关联可以分成一对一、一对多、多对一和多对多关联

 

 

Product2.java

package hibernate.example.vo;

public class Product2 {

private Integer id;

private String name;

private Double price;

private String description;

private Category category;

public Product2() {

super();

}

 

public Integer getId() {

return id;

}

 

public void setId(Integer id) {

this.id = id;

}

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

public Double getPrice() {

return price;

}

 

public void setPrice(Double price) {

this.price = price;

}

 

public String getDescription() {

return description;

}

 

public void setDescription(String description) {

this.description = description;

}

 

public Category getCategory() {

return category;

}

 

public void setCategory(Category category) {

this.category = category;

}

}

Product2.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="hibernate.example.vo.Product2" table="PRODUCT2">

        <id name="id" column="ID" type="java.lang.Integer">

            <generator class="increment" />

        </id>

        <property name="name" column="NAME" type="java.lang.String"/>

        <property name="price" column="PRICE" type="java.lang.Double"/>

        <property name="description" column="DESCRIPTION" type="java.lang.String"/>

        <!– 关联查询 outer-join="true",设置这个则只显示一条SQL语句,否则显示两条语句 –>

        <many-to-one name="category" class="hibernate.example.vo.Category" outer-join="true">

            <column name="CATEGORY_ID"/>

        </many-to-one>

    </class>

</hibernate-mapping>

Category.java

package hibernate.example.vo;

public class Category {

private Integer id;

private String name;

private String description;

public Category() {

super();

}

 

public Integer getId() {

return id;

}

 

public void setId(Integer id) {

this.id = id;

}

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

public String getDescription() {

return description;

}

 

public void setDescription(String description) {

this.description = description;

}

}

Category.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="hibernate.example.vo.Category" table="CATEGORY">

        <id name="id" column="ID" type="java.lang.Integer">

            <generator class="increment" />

        </id>

        <property name="name" column="NAME" type="java.lang.String"/>

        <property name="description" column="DESCRIPTION" type="java.lang.String"/>

    </class>

</hibernate-mapping>

Many2OneMappingTest.java

package hibernate.example.test;

import java.util.List;

import hibernate.example.util.HibernateSessionFactoryUtil;

import hibernate.example.vo.Category;

import hibernate.example.vo.Product2;

import org.hibernate.Query;

import org.hibernate.Session;

public class Many2OneMappingTest {

 

    public static void main(String[] args) {

        new Many2OneMappingTest().addCategory();

        new Many2OneMappingTest().addProduct();

        new Many2OneMappingTest().loadProduct();

        new Many2OneMappingTest().listProducts();

        new Many2OneMappingTest().updateProduct();

        new Many2OneMappingTest().deleteProduct();

    }

   

    public void addCategory(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Category c = new Category();

        c.setName("Laptop");

        c.setDescription("All Laptops");

        session.save(c);

        session.getTransaction().commit();

    }

   

    public void addProduct(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Product2 p = new Product2();

        p.setName("Thinkpad X200");

        p.setDescription("IBM Thinkpad");

        p.setPrice(5000.0);

        Category c = (Category)session.get(Category.class, new Integer(2));

        p.setCategory(c);

        session.save(p);

        session.getTransaction().commit();     

    }

   

    public void loadProduct(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Product2 p = (Product2)session.get(Product2.class, new Integer(1));

        System.out.println(p.getId());

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

        System.out.println(p.getDescription());

        System.out.println(p.getPrice());

        Category c = p.getCategory();      

        System.out.println(c.getId());

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

        System.out.println(c.getDescription());

        session.getTransaction().commit();     

    }

   

    public void listProducts(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();    

        Query query = session.createQuery("FROM Product2 ORDER BY id");

        @SuppressWarnings("unchecked")

        List<Product2> list = query.list();

        for(Product2 p: list){

            System.out.println(p.getId());

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

            System.out.println(p.getDescription());

            System.out.println(p.getPrice());

            Category c = p.getCategory();

            System.out.println(c.getId());

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

            System.out.println(c.getDescription());        

        }

        session.getTransaction().commit();         

    }

   

    public void updateProduct(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Product2 p = (Product2)session.get(Product2.class, new Integer(2));

        p.setPrice(0.1);

        Category c = (Category)session.get(Category.class, new Integer(1));

        p.setCategory(c);

        session.getTransaction().commit();     

    }  

   

    public void deleteProduct(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Product2 p = (Product2)session.get(Product2.class, new Integer(2));

        session.delete(p);

        session.getTransaction().commit();     

    }      

}

 

一对多单向关联

Product与Category是多对一的关系,Product对象维护者对Category对象的参考,如果由Category对象维护对多个Product对象的管理,就是一对多单向关联

Product3.java

package hibernate.example.vo;

public class Product3 {

private Integer id;

private String name;

private Double price;

private String description;

public Product3() {

super();

}

 

public Integer getId() {

return id;

}

 

public void setId(Integer id) {

this.id = id;

}

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

public Double getPrice() {

return price;

}

 

public void setPrice(Double price) {

this.price = price;

}

 

public String getDescription() {

return description;

}

 

public void setDescription(String description) {

this.description = description;

}

}

 

Product3.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="hibernate.example.vo.Product3" table="PRODUCT2">

        <id name="id" column="ID" type="java.lang.Integer">

            <generator class="increment" />

        </id>

        <property name="name" column="NAME" type="java.lang.String"/>

        <property name="price" column="PRICE" type="java.lang.Double"/>

        <property name="description" column="DESCRIPTION" type="java.lang.String"/>

    </class>

</hibernate-mapping>

Category3.java

package hibernate.example.vo;

import java.util.HashSet;

import java.util.Set;

public class Category3 {

    private Integer id;

    private String name;

    private String description;

    private Set<Product3> products = new HashSet<Product3>();

   

    public Category3() {

        super();

    }

 

    public Integer getId() {

        return id;

    }

 

    public void setId(Integer id) {

        this.id = id;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public String getDescription() {

        return description;

    }

 

    public void setDescription(String description) {

        this.description = description;

    }

 

    public Set<Product3> getProducts() {

        return products;

    }

 

    public void setProducts(Set<Product3> products) {

        this.products = products;

    }

}


Category3.hbm.xml
<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

                                   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

 <class name="hibernate.example.vo.Category3" table="CATEGORY">

  <cache usage="read-write"/>

  <id column="ID" name="id" type="java.lang.Integer">

   <generator class="increment"/>

  </id>

  <property column="NAME" generated="never" lazy="false" name="name" type="java.lang.String"/>

  <property column="DESCRIPTION" generated="never" lazy="false"

   name="description" type="java.lang.String"/>

  <set cascade="save-update" name="products" sort="unsorted">

   <cache usage="read-write"/>

   <key column="CATEGORY_ID"/>

   <one-to-many class="hibernate.example.vo.Product3"/>

  </set>

 </class>

</hibernate-mapping>

 

One2ManayMappingTest.java
package hibernate.example.test;
import hibernate.example.util.HibernateSessionFactoryUtil;
import hibernate.example.vo.Category3;
import hibernate.example.vo.Product3;
import java.util.Set;
import org.hibernate.Session;
public class One2ManyMappingTest { 

    public static void main(String[] args) {

        new One2ManyMappingTest().addCategory();

        new One2ManyMappingTest().addProduct();

        new One2ManyMappingTest().listProducts();

        new One2ManyMappingTest().updateCategory();

        new One2ManyMappingTest().deleteCategory();

        new One2ManyMappingTest().addCatPro();

    }

   

    public void addCategory(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Category3 c = new Category3();

        c.setName("Pad");

        c.setDescription("All Pads");

        session.save(c);

        session.getTransaction().commit();

    }

   

    public void addProduct(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Product3 p = new Product3();

        p.setName("Ipad I");

        p.setDescription("Ipad I");

        p.setPrice(5000.0);

       

        Category3 c = (Category3)session.get(Category3.class, new Integer(3));

        Set<Product3> products = c.getProducts();

        products.add(p);

        //当不使用cascade="save-update"时,需要提供save(p)方法,否则会提示org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing

        //当使用cascade="save-update"时,不需要提供save(p)

        session.save(p);

        session.save(c);

        session.getTransaction().commit();     

    }

   

    public void addCatPro(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

       

        Category3 c = new Category3();

        c.setName("Books");

        c.setDescription("All Books");

       

        Product3 p1 = new Product3();

        p1.setName("Computer and Science");

        p1.setDescription("Internet");

        p1.setPrice(30.0);

        c.getProducts().add(p1);

       

        Product3 p2 = new Product3();

        p2.setName("Longman Dictionary");

        p2.setDescription("Dictionary");

        p2.setPrice(85.0);

        c.getProducts().add(p2);

       

        session.save(c);

        //使用cascade="save-update"不需要提供对于级联对象的保存操作,见下面注释代码

//      session.save(p1);

//      session.save(p2);

        session.getTransaction().commit();     

    }  

   

    public void listProducts(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();    

        Category3 c = (Category3)session.get(Category3.class, new Integer(2));

        Set<Product3> ps = c.getProducts();

       

        for(Product3 p: ps){

            System.out.println(p.getId());

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

            System.out.println(p.getDescription());

            System.out.println(p.getPrice());

            System.out.println(c.getId());

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

            System.out.println(c.getDescription());        

        }

        session.getTransaction().commit();         

    }

   

    public void updateCategory(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Category3 c = (Category3)session.get(Category3.class, new Integer(2));

        c.setName("XXX");

        session.update(c);

        session.getTransaction().commit();     

    }  

   

    public void deleteCategory(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Category3 c = (Category3)session.get(Category3.class, new Integer(2));

        Set<Product3> ps = c.getProducts();

        Category3 c2 = (Category3)session.get(Category3.class, new Integer(1));

        c2.setProducts(ps);

        session.delete(c);

        session.getTransaction().commit();     

    }      

}

 

级联(Cascade)

主动方对象执行操作时,被关联的对象(被动方)是否同步执行同一操作

<set cascade="save-update" name="products">

 <key column="CATEGORY_ID"/>

 <one-to-many class="hibernate.example.vo.Product3"/>

</set>

 

级联(cascade)

none

cascade的默认值,表示关联对象之间没有任何级联操作

save-update

表示主动对象在调用save(), update()和saveOrUpdate()方法时对被关联对象进行级联操作

delete

表示主动方对象在调用delete()方法时对被关联对象进行级联操作

delete-orphan

只应用于一对多关联,表明主动方对象调用delete()方法,此时不被任何一个关联对象所引用被关联对象会被删除

all

关联对象之间全部操作都顺着关联关系级联

 

一对多双向关联

Product4.java

package hibernate.example.vo;

public class Product4 {

private Integer id;

private String name;

private Double price;

private String description;

private Category4 category;

public Product4() {

super();

}

 

public Integer getId() {

return id;

}

 

public void setId(Integer id) {

this.id = id;

}

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

public Double getPrice() {

return price;

}

 

public void setPrice(Double price) {

this.price = price;

}

 

public String getDescription() {

return description;

}

 

public void setDescription(String description) {

this.description = description;

}

 

public Category4 getCategory() {

return category;

}

 

public void setCategory(Category4 category) {

this.category = category;

}

}

 

Product4.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="hibernate.example.vo.Product4" table="PRODUCT2">

        <id name="id" column="ID" type="java.lang.Integer">

            <generator class="increment" />

        </id>

        <property name="name" column="NAME" type="java.lang.String"/>

        <property name="price" column="PRICE" type="java.lang.Double"/>

        <property name="description" column="DESCRIPTION" type="java.lang.String"/>

        <!– 关联查询 outer-join="true",设置这个则只显示一条SQL语句,否则显示两条语句 –>

        <many-to-one name="category" class="hibernate.example.vo.Category4" outer-join="true">

            <column name="CATEGORY_ID"/>

        </many-to-one>

    </class>

</hibernate-mapping>

 

Category4.java

package hibernate.example.vo;

import java.util.HashSet;

import java.util.Set;

public class Category4 {

    private Integer id;

    private String name;

    private String description;

    private Set<Product4> products = new HashSet<Product4>();

   

    public Category4() {

        super();

    }

 

    public Integer getId() {

        return id;

    }

 

    public void setId(Integer id) {

        this.id = id;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public String getDescription() {

        return description;

    }

 

    public void setDescription(String description) {

        this.description = description;

    }

 

    public Set<Product4> getProducts() {

        return products;

    }

 

    public void setProducts(Set<Product4> products) {

        this.products = products;

    }

}

 

Category4.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

                                   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

 <class name="hibernate.example.vo.Category4" table="CATEGORY">

  <id column="ID" name="id" type="java.lang.Integer">

   <generator class="increment"/>

  </id>

  <property column="NAME" generated="never" lazy="false" name="name" type="java.lang.String"/>

  <property column="DESCRIPTION" generated="never" lazy="false" name="description" type="java.lang.String"/>

  <!–

          表示关联关系的维护工作由谁来负责,默认为false,表示由主控方负责关联关系的维护,

          如果设置为true则表示将由被控方来维护关联关系

          如果没有inverse属性,插入数据的时候对于product来说需要两个步骤:1. insert一个空外键的product数据集 2. update这个外键

          如果设置这个属性为true,则只需要插入一条数据

   –>

  <set name="products" inverse="true">

   <key column="CATEGORY_ID"/>

   <one-to-many class="hibernate.example.vo.Product4"/>

  </set>

 </class>

</hibernate-mapping>

 

One2ManyDuaDirectionMapping.java

package hibernate.example.test;

import hibernate.example.util.HibernateSessionFactoryUtil;

import hibernate.example.vo.Category4;

import hibernate.example.vo.Product4;

import org.hibernate.Session;

public class One2ManyDuaDirectionMappingTest {

 

    public static void main(String[] args) {

        new One2ManyDuaDirectionMappingTest().add();

    }

   

    public void add(){

        Session session = HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Category4 c = new Category4();

        c.setName("Music");

        c.setDescription("All music");

        Product4 p1 = new Product4();

        p1.setName("苏格拉没有底");

        p1.setDescription("许嵩 – 苏格拉没有底");

        p1.setPrice(20.0);

 

        Product4 p2 = new Product4();

        p2.setName("爱情里的眼泪");

        p2.setDescription("许嵩 – 爱情里的眼泪");

        p2.setPrice(20.0);

       

        //1-N | N-1 双向关联

        p1.setCategory(c);

        p2.setCategory(c);

        c.getProducts().add(p1);

        c.getProducts().add(p2);

       

        session.save(c);

        session.save(p1);

        session.save(p2);

       

        session.getTransaction().commit();

    }

}

 

控制反转(inverse)

在Hibernate中的一对多的单向或者双向关联的情况下,我可以将"一"方控制权交给"多"方,称为控制反转(inverse)

  <set name="products" inverse="true">

   <key column="CATEGORY_ID"/>

   <one-to-many class="hibernate.example.vo.Product4"/>

  </set>

Advertisements
 
Leave a comment

Posted by on 04/03/2011 in HIBERNATE

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

 
%d bloggers like this: