Hibernate学习---第七节:关联关系
一、关联关系一对一外键(双向)
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(),控制台打印:
(2)、测试 testGet(),控制台打印:
(3)、测试 testGet2(),控制台打印:
(4)、测试 testUpdate(),控制台打印:
(5)、测试 testDel(),控制台打印:
如果映射配置文件没有添加 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
Hibernate学习---第七节:关联关系的更多相关文章
- VUE2.0实现购物车和地址选配功能学习第七节
第七节 卡片选中,设置默认 1.卡片选中html:<li v-for="(item,index) in filterAddress" v-bind:class="{ ...
- SSH:Hibernate框架(七种关联关系映射及配置详解)
概念 基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用. 分类 关联关系分为上述七种,但是由于相互之间有各种关系, ...
- Hibernate学习---第六节:数组&list&map&set的映射配置
1.实体类,代码如下: package learn.hibernate.bean; import java.util.Date; import java.util.HashMap; import ja ...
- Hibernate学习---第五节:普通组件和动态组件
一.普通组件映射配置 1.创建组件类,代码如下: package learn.hibernate.bean; /** * 组件类 */ public class Phones { private St ...
- Hibernate学习(七)———— hibernate中查询方式详解
序言 之前对hibernate中的查询总是搞混淆,不明白里面具体有哪些东西.就是因为缺少总结.在看这篇文章之前,你应该知道的是数据库的一些查询操作,多表查询等 --WH 一.hibernate中的5种 ...
- Coursera在线学习---第七节.支持向量机(SVM)
一.代价函数 对比逻辑回归与支持向量机代价函数. cost1(z)=-log(1/(1+e-z)) cost0(z)=-log(1-1/(1+e-z)) 二.支持向量机中求解代价函数中的C值相当于 ...
- Hibernate学习---第十一节:Hibernate之数据抓取策略&批量抓取
1.hibernate 也可以通过标准的 SQL 进行查询 (1).将SQL查询写在 java 代码中 /** * 查询所有 */ @Test public void testQuery(){ // ...
- Hibernate学习(七)
Hibernate缓存 1.一级缓存:Session 级别的缓存 2.二级缓存: SessionFactory 级别的缓存 3.查询缓存:需二级缓存的支持,查询缓存依赖二级缓存 一级缓存 1.依赖于 ...
- JPA学习---第七节:使用JPA加载_更新_删除对象
1.添加数据,代码如下: @Test public void save(){ EntityManagerFactory factory = Persistence.createEntityManage ...
随机推荐
- Ubuntu配置apache2.4配置虚拟主机遇到的问题
update: 偶然看到了 apache的更新说明,直接贴个地址过来吧. http://httpd.apache.org/docs/2.4/upgrading.html 最近想把web开发目录从/va ...
- 通俗的解释下音视频同步里pcr作用
PCR同步在非硬件精确时钟源的情况还是谨慎使用,gstreamer里面采用PCR同步,但是发现好多ffmpeg转的片儿,或者是CP方的片源,pcr打得很粗糙的,老是有跳帧等现象.音视频同步,有三种方法 ...
- 嵌入式开发之davinci--- 8148/8168/8127 中的High-DefinitionVideo Processing Subsystem (HDVPSS)
High-DefinitionVideo Processing Subsystem (HDVPSS) 这一章介绍了高清视频处理子系统(HDVPSS). 2.1导论 2.1.1 简介 HDVPSS 使用 ...
- 解决Java工程URL路径中含有中文的情况
问题: 当Java工程路径中含有中文时,得不到正确的路径 *** 解决: 这其实是编码转换的问题.当我们使用ClassLoader的getResource方法获取路径时,获取到的路径被URLEncod ...
- Python小白的发展之路之Python基础(三)【函数简介】
目录: 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 4.嵌套函数 5.递归 6.匿名函数 7.函数式编程介绍 8.高阶函数 9.内置函数 1. 函数基本语法及特性 首先我们明确函数是 ...
- unity里standard pbr(一)
关注forwardbase下的 standard.shader #pragma vertex vertBase #pragma fragment fragBase #include "Uni ...
- Django 基于Ajax & form 简单实现文件上传
前端实现 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="U ...
- 我的Android进阶之旅------>Android KeyCode列表
KEYCODE列表 电话键 KEYCODE_CALL 拨号键 5 KEYCODE_ENDCALL 挂机键 6 KEYCODE_HOME 按键Home 3 KEYCODE_MENU 菜单键 82 KEY ...
- android 中使用svg
http://www.see-source.com/blog/300000038/1189.html http://www.jianshu.com/p/30dfa5920658#
- 记一次bash脚本报错原因
准备部署上次写的 爬虫的定时任务,发现sh脚本 写为最简单的cd ,也报错 后来网上一波了解,原因竟是 : 额,格式问题,我为了图方便是在window里用notepad++写的,然后我再linux 系 ...