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

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(),控制台打印:

Hibernate学习---第七节:关联关系-LMLPHP

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

Hibernate学习---第七节:关联关系-LMLPHP

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

Hibernate学习---第七节:关联关系-LMLPHP

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

Hibernate学习---第七节:关联关系-LMLPHP

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

Hibernate学习---第七节:关联关系-LMLPHP

如果映射配置文件没有添加  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 的级联操作详解

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

05-27 15:01