一、关联关系一对一外键(双向)

1、实体类,代码如下:

package learn.hibernate.bean;

import java.util.Date;

/**
 * 持久化类设计
 * 注意:
 *         持久化类通常建议要有一个持久化标识符(ID)
 *         持久化标识符通常建议使用封装类(例如:Integer  因为基本类型存在默认值)
 *         持久化类通常建议手动添加一个无参构造函数 (因为有些操作是通过放射机制进行的)
 *         属性通常建议提供  getter/setter 方法
 *         持久化类不能使用 final 修饰
 *         持久化类中如果使用了集合类型数据,只能使用集合所对应的接口类型来声明(List/Map/Set)
 *              如下:ArrayList list = new ArrayList();  不行
 *                 List list = new ArrayList(); 可行
 */
public class Person {

    private Integer id;
    private String name;
    private int age;
    private int passwork;
    private Date birthday;
    
    private Address addres;
    
    public Person() {
        
    }
    
    public Person(String name, int age, int passwork, Date birthday) {
        super();
        this.name = name;
        this.age = age;
        this.passwork = passwork;
        this.birthday = birthday;
    }
    
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age
                + ", passwork=" + passwork + ", birthday=" + birthday + "]";
    }
    
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getPasswork() {
        return passwork;
    }
    public void setPasswork(int passwork) {
        this.passwork = passwork;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Address getAddres() {
        return addres;
    }

    public void setAddres(Address addres) {
        this.addres = addres;
    }
    
}
package learn.hibernate.bean;

public class Address {

    private Integer id;
    private String zipCode;
    private String address;
    private Person person;
    
    public Address() {
        super();
    }
    
    public Address(String zipCode, String address) {
        super();
        this.zipCode = zipCode;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address [zipCode=" + zipCode + ", address=" + address + "]";
    }
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getZipCode() {
        return zipCode;
    }
    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

2、映射配置,代码如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="learn.hibernate.bean">
    <class name="Person" table="t_person">
        <id name="id" column="person_id">
            <generator class="native"/>
        </id>
        <property name="name" column="t_name"/>
        <property name="age"/>    
        <property name="passwork"/>
        <property name="birthday"/>
        <!-- 
            one-to-one 表示一对一的配置
            name 指定 Person 类中的关联关系的 address 属性
            cascade 表示级联操作
                级联是对象之间的关联操作,只影响添加、删除、更新,不影响查询
                all:所有情况下都进行关联操作(save、update、delete)
                none:所有情况下都不进行关联操作(默认值)
                save-update:在执行 (save、update、saveOrUpdate)进行关联操作
                delete:在执行 delete 时进行关联操作
         -->
        <one-to-one name="addres" cascade="all"/>
    </class>
    <class name="Address" table="t_address">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="zipCode"/>
        <property name="address"/>
        <!-- 
            基于外键的一对一配置,在从表一端使用 many-to-one 
            name Address类中关联关系 Person 类的引用变量名
            column 指定外键列名,可选
            unique 唯一约束,因为使用的是一对一外键关联
            not-null 指定列是否为空
         -->
        <many-to-one name="person" column="person_id" unique="true" not-null="true"/>
    </class>
</hibernate-mapping>

3、测试类,代码如下:

package learn.hibernate.test;

import static org.junit.Assert.*;

import java.util.Date;

import learn.hibernate.bean.Address;
import learn.hibernate.bean.Person;
import learn.hibernate.bean.Phones;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHibernate {

    SessionFactory factory = null;
    Session session = null;
    Transaction tx = null;
    
    /**
     * 测试之前初始化数据
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    @Before
    public void setUp() throws Exception {
        System.out.println("---------初始化数据----------");
        
        Configuration config = new Configuration().configure();
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        factory = config.buildSessionFactory(sr);
        session = factory.openSession();
    }

    /**
     * 测试之后释放(销毁)数据
     * @throws Exception
     */
    @After
    public void tearDown() throws Exception {
        System.out.println("---------释放数据----------");
        if(session.isOpen()){
            session.close();
        }
    }
    
    @Test
    public void testAdd(){
        Person p = new Person("tiger",22,123456,new Date());
        Address address = new Address("410000","湖南长沙");
        p.setAddres(address);
        address.setPerson(p);
        
        tx = session.beginTransaction();
        // 进行数据保存的时候先持久化主表,在持久化从表;否则会执行 update 语句
        session.persist(p);
        session.persist(address);
        tx.commit();
    }
    
    /**
     * 通过主表获取数据
     * 通过 left outer join 进行数据查询
     */
    @Test
    public void testGet(){
        Person p = (Person)session.get(Person.class, 1);
        System.out.println(p);
        System.out.println("------------------------");
        System.out.println(p.getAddres());
    }
    
    /**
     * 通过从表获取数据
     * 先查询从表数据,获取主表数据时再通过 left outer join 进行数据查询
     */
    @Test
    public void testGet2(){
        Address address = (Address)session.get(Address.class, 1);
        System.out.println(address);
        System.out.println("------------------------");
        System.out.println(address.getPerson());
    }
    
    /**
     * 更新
     */
    @Test
    public void testUpdate(){
        Person p = (Person)session.get(Person.class, 2);
        p.setAge(25);
        Address address = p.getAddres();
        address.setAddress("湖北武汉");
        tx = session.beginTransaction();
        session.merge(p);
        tx.commit();
    }
    
    /**
     * 删除
     */
    @Test
    public void testDel(){
        tx = session.beginTransaction();
        Person p = (Person)session.get(Person.class, 1);
        session.delete(p);
        tx.commit();
    }
}

4、测试

(1)、测试 testAdd(),控制台打印:

QQ截图20141217210833

(2)、测试 testGet(),控制台打印:

QQ截图20141217210929

(3)、测试 testGet2(),控制台打印:

QQ截图20141217211012

(4)、测试 testUpdate(),控制台打印:

QQ截图20141217212434

(5)、测试 testDel(),控制台打印:

QQ截图20141217211733

如果映射配置文件没有添加  cascade="all" 或者  cascade="delete",删除的时候会报如下错误:

org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3400)
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3630)
    at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:114)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at learn.hibernate.test.TestHibernate.testDel(TestHibernate.java:115)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`hibernate`.`t_address`, CONSTRAINT `FK_sydlu68t7mra095us6fku8eyt` FOREIGN KEY (`person_id`) REFERENCES `t_person` (`person_id`))
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2427)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2345)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2330)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
    ... 38 more

 

三、关联关系一对一主键(双向)

除了配置文件不一样之外,其他的都是一样的;配置文件代码如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="learn.hibernate.bean">
    <class name="Person" table="t_person">
        <id name="id" column="person_id">
            <generator class="native"/>
        </id>
        <property name="name" column="t_name"/>
        <property name="age"/>    
        <property name="passwork"/>
        <property name="birthday"/>
        <one-to-one name="addres" cascade="all"/>
    </class>
    <class name="Address" table="t_address">
        <id name="id">
            <!-- 表示adderss的主键不再由 自己产生,而是使用Person对应表的主键 -->
            <generator class="foreign">
                <param name="property">person</param>
            </generator>
        </id>
        <property name="zipCode"/>
        <property name="address"/>
        <!-- 
            基于 主键 的 一对一 双向 关联 
            constrained 表示主键约束 true表示启用主键约束
        -->
        <one-to-one name="person" constrained="true"/>
    </class>
</hibernate-mapping>

 

四、关联关系一对多(双向)

1、实体类,代码如下:

package learn.hibernate.bean;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * 持久化类设计
 * 注意:
 *         持久化类通常建议要有一个持久化标识符(ID)
 *         持久化标识符通常建议使用封装类(例如:Integer  因为基本类型存在默认值)
 *         持久化类通常建议手动添加一个无参构造函数 (因为有些操作是通过放射机制进行的)
 *         属性通常建议提供  getter/setter 方法
 *         持久化类不能使用 final 修饰
 *         持久化类中如果使用了集合类型数据,只能使用集合所对应的接口类型来声明(List/Map/Set)
 *              如下:ArrayList list = new ArrayList();  不行
 *                 List list = new ArrayList(); 可行
 */
public class Person {

    private Integer id;
    private String name;
    private int age;
    private int passwork;
    private Date birthday;
    
    private Set<Address> addres = new HashSet<Address>();
    
    public Person() {
        
    }
    
    public Person(String name, int age, int passwork, Date birthday) {
        super();
        this.name = name;
        this.age = age;
        this.passwork = passwork;
        this.birthday = birthday;
    }
    
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age
                + ", passwork=" + passwork + ", birthday=" + birthday + "]";
    }
    
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getPasswork() {
        return passwork;
    }
    public void setPasswork(int passwork) {
        this.passwork = passwork;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Set<Address> getAddres() {
        return addres;
    }

    public void setAddres(Set<Address> addres) {
        this.addres = addres;
    }
}

2、配置文件,代码如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="learn.hibernate.bean">
    <class name="Person" table="t_person">
        <id name="id" column="person_id">
            <generator class="native"/>
        </id>
        <property name="name" column="t_name"/>
        <property name="age"/>    
        <property name="passwork"/>
        <property name="birthday"/>
        <!-- 
            通过Set配置一个人对应的多个地址的关联关系
            inverse=true 表示在Person端不维护关系;因为多的一端有外键,管理关联关系更高效
         -->
        <set name="addres" cascade="all" inverse="true">
            <!-- 指定 addres 集合中的数据对应t_person的的一个外键 -->
            <key column="p_id"/>
            <!-- 指定Person 关联的实例类型 -->
            <one-to-many class="Address"/>
        </set>
        
        <!-- inverse="false" 一定要为 false 因为要控制顺序 -->
        <!-- <list name="addres" inverse="false" cascade="all">
            <key column="p_id"/>
            <index column="indexs" type="integer"/>
            <one-to-many class="Address"/>
        </list> -->
        <!-- inverse="false" 一定要为 false 因为要控制顺序 -->
        <!-- <map name="addres" inverse="false" cascade="all">
            <key column="p_id"/>
            <index column="map_key" type="string"/>
            <one-to-many class="Address"/>
        </map> -->
    </class>
    <class name="Address" table="t_address">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="zipCode"/>
        <property name="address"/>
        <!-- 
            多的一端使用 many-to-one 进行配置 
        -->
        <many-to-one name="person" column="p_id"/>
    </class>
</hibernate-mapping>

3、测试代码,如下:

package learn.hibernate.test;

import static org.junit.Assert.*;

import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import learn.hibernate.bean.Address;
import learn.hibernate.bean.Person;
import learn.hibernate.bean.Phones;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHibernate {

    SessionFactory factory = null;
    Session session = null;
    Transaction tx = null;
    
    /**
     * 测试之前初始化数据
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    @Before
    public void setUp() throws Exception {
        System.out.println("---------初始化数据----------");
        
        Configuration config = new Configuration().configure();
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        factory = config.buildSessionFactory(sr);
        session = factory.openSession();
    }

    /**
     * 测试之后释放(销毁)数据
     * @throws Exception
     */
    @After
    public void tearDown() throws Exception {
        System.out.println("---------释放数据----------");
        if(session.isOpen()){
            session.close();
        }
    }
    
    @Test
    public void testAdd(){
        Person p = new Person("tiger",22,123456,new Date());
        Address address1 = new Address("410000","湖南长沙");
        Address address2 = new Address("410001","湖南郴州");
        Address address3 = new Address("410002","湖南常德");
        Address address4 = new Address("410003","湖南衡阳");
        
        Set<Address> set = new HashSet<Address>();
        
        set.add(address1);
        set.add(address2);
        set.add(address3);
        set.add(address4);
        
        // person 与多个 Address 建立关联
        p.setAddres(set);
        // Address 与 person 建立关联;如果不建立关联,那么外键为 null
        address1.setPerson(p);
        address2.setPerson(p);
        address3.setPerson(p);
        address4.setPerson(p);
        
        tx = session.beginTransaction();
        session.persist(p);
        tx.commit();
    }
    
    /**
     * 通过主表获取数据
     * 通常从表的数据时延迟查询
     */
    @Test
    public void testGet(){
        Person p = (Person)session.get(Person.class, 1);
        System.out.println(p);
        System.out.println("------------------------");
        Iterator<Address> it = p.getAddres().iterator();
        while(it.hasNext()){
            Address address = it.next();
            System.out.println(address);
        }
    }
    
    /**
     * 通过从表获取数据
     * 先查询从表数据,主表数据是延迟查询
     */
    @Test
    public void testGet2(){
        Address address = (Address)session.get(Address.class, 1);
        System.out.println(address);
        System.out.println("------------------------");
        System.out.println(address.getPerson());
    }
    
    /**
     * 删除主表时,会将所对应的从表数据删除
     */
    @Test
    public void testDel(){
        tx = session.beginTransaction();
        Person p = (Person)session.get(Person.class, 1);
        session.delete(p);
        tx.commit();
    }
    
    /**
     * 删除从表数据,只会删除从表自己的数据
     */
    @Test
    public void testDel2(){
        tx = session.beginTransaction();
        Address address = (Address)session.get(Address.class, 5);
        session.delete(address);
        tx.commit();
    }
}

 

五、关联关系多对多(双向)

1、实体类,代码如下:

package learn.hibernate.bean;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * 持久化类设计
 * 注意:
 *         持久化类通常建议要有一个持久化标识符(ID)
 *         持久化标识符通常建议使用封装类(例如:Integer  因为基本类型存在默认值)
 *         持久化类通常建议手动添加一个无参构造函数 (因为有些操作是通过放射机制进行的)
 *         属性通常建议提供  getter/setter 方法
 *         持久化类不能使用 final 修饰
 *         持久化类中如果使用了集合类型数据,只能使用集合所对应的接口类型来声明(List/Map/Set)
 *              如下:ArrayList list = new ArrayList();  不行
 *                 List list = new ArrayList(); 可行
 */
public class Person {

    private Integer id;
    private String name;
    private int age;
    private int passwork;
    private Date birthday;
    
    private Set<Address> addres = new HashSet<Address>();
    
    public Person() {
        
    }
    
    public Person(String name, int age, int passwork, Date birthday) {
        super();
        this.name = name;
        this.age = age;
        this.passwork = passwork;
        this.birthday = birthday;
    }
    
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age
                + ", passwork=" + passwork + ", birthday=" + birthday + "]";
    }
    
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getPasswork() {
        return passwork;
    }
    public void setPasswork(int passwork) {
        this.passwork = passwork;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Set<Address> getAddres() {
        return addres;
    }

    public void setAddres(Set<Address> addres) {
        this.addres = addres;
    }
}
package learn.hibernate.bean;

import java.util.Set;

public class Address {

    private Integer id;
    private String zipCode;
    private String address;
    private Set<Person> person;
    
    public Address() {
        
    }
    
    public Address(String zipCode, String address) {
        super();
        this.zipCode = zipCode;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address [zipCode=" + zipCode + ", address=" + address + "]";
    }
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getZipCode() {
        return zipCode;
    }
    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }

    public Set<Person> getPerson() {
        return person;
    }

    public void setPerson(Set<Person> person) {
        this.person = person;
    }
}

2、配置文件,代码如下:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="learn.hibernate.bean">
    <class name="Person" table="t_person">
        <id name="id" column="person_id">
            <generator class="native"/>
        </id>
        <property name="name" column="t_name"/>
        <property name="age"/>    
        <property name="passwork"/>
        <property name="birthday"/>
        <!-- 
            通过Set配置一个人对应的多个地址的关联关系
            inverse=true 表示在Person端不维护关系;因为多的一端有外键,管理关联关系更高效
         -->
        <set name="addres" cascade="all" inverse="true" table="person_address">
            <!-- 指定 addres 集合中的数据对应t_person的的一个外键 -->
            <key column="p_id"/>
            <!-- 指定Person 关联的实例类型 -->
            <many-to-many class="Address" column="a_id"/>
        </set>
    </class>
    <class name="Address" table="t_address">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="zipCode"/>
        <property name="address"/>
        
        <set name="person" cascade="all" table="person_address">
            <key column="a_id"/>
            <many-to-many class="Person" column="p_id"/>
        </set>
    </class>
</hibernate-mapping>

3、测试类,代码如下:

package learn.hibernate.test;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import learn.hibernate.bean.Address;
import learn.hibernate.bean.Person;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHibernate {

    SessionFactory factory = null;
    Session session = null;
    Transaction tx = null;
    
    /**
     * 测试之前初始化数据
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    @Before
    public void setUp() throws Exception {
        System.out.println("---------初始化数据----------");
        
        Configuration config = new Configuration().configure();
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        factory = config.buildSessionFactory(sr);
        session = factory.openSession();
    }

    /**
     * 测试之后释放(销毁)数据
     * @throws Exception
     */
    @After
    public void tearDown() throws Exception {
        System.out.println("---------释放数据----------");
        if(session.isOpen()){
            session.close();
        }
    }
    
    @Test
    public void testAdd(){
        Person p1 = new Person("tiger",22,123456,new Date());
        Person p2 = new Person("admin",25,123456,new Date());
        
        Set<Person> pset = new HashSet<Person>();
        pset.add(p1);
        pset.add(p2);
        
        Address address1 = new Address("410000","湖南长沙");
        Address address2 = new Address("410001","湖南郴州");
        Address address3 = new Address("410002","湖南常德");
        Address address4 = new Address("410003","湖南衡阳");
        
        Set<Address> set = new HashSet<Address>();
        
        set.add(address1);
        set.add(address2);
        set.add(address3);
        set.add(address4);
        
        // person 与多个 Address 建立关联
        p1.setAddres(set);
        p2.setAddres(set);
        
        // Address 与 person 建立关联;如果不建立关联,那么外键为 null
        address1.setPerson(pset);
        address2.setPerson(pset);
        address3.setPerson(pset);
        address4.setPerson(pset);
        
        tx = session.beginTransaction();
        session.persist(p1);
        session.persist(p2);
        tx.commit();
    }
    
    /**
     * 通过主表获取数据
     * 通常从表的数据时延迟查询
     */
    @Test
    public void testGet(){
        Person p = (Person)session.get(Person.class, 3);
        System.out.println(p);
        System.out.println("------------------------");
        Iterator<Address> it = p.getAddres().iterator();
        while(it.hasNext()){
            Address address = it.next();
            System.out.println(address);
        }
    }
    
    /**
     * 通过从表获取数据
     * 先查询从表数据,主表数据是延迟查询
     */
    @Test
    public void testGet2(){
        Address address = (Address)session.get(Address.class, 9);
        System.out.println(address);
        System.out.println("------------------------");
        Set<Person> pset = address.getPerson();
        Person[] p = new Person[pset.size()];
        pset.toArray(p);
        System.out.println(Arrays.toString(p));
    }
}

六、hibernate 的级联操作详解

cascade属性表明操作是否从父对象级联到被关联的对象,它的取得可以是以下几种:
none:在保存,删除或修改当前对象时,不对其附属对象(关联对象)进行级联操作。它是默认值。
save-update:在保存,更新当前对象时,级联保存,更新附属对象(临时对象,游离对象)。
delete:在删除当前对象时,级联删除附属对象。
all:所有情况下均进行级联操作,即包含save-update和delete操作。
delete-orphan:删除和当前对象解除关系的附属对象。

以上的文字来自:http://blog.csdn.net/owen_008/article/details/4429382

posted on 2015-02-04 19:39  hwlsniper  阅读(233)  评论(0编辑  收藏  举报