单向N-1关系,比如多个人对应同一个住址,只需要从人实体端找到对应的住址实体,无须关系某个地址的全部住户。程序在N的一端增加一个属性,该属性引用1的一端的关联实体。
例如下面person实体中的address属性,
1 package map.six11; 2 3 public class Person { 4 public Integer getId() { 5 return id; 6 } 7 public void setId(Integer id) { 8 this.id = id; 9 } 10 public int getAge() { 11 return age; 12 } 13 public void setAge(int age) { 14 this.age = age; 15 } 16 public String getName() { 17 return name; 18 } 19 public void setName(String name) { 20 this.name = name; 21 } 22 public Address getAddress() { 23 return address; 24 } 25 public void setAddress(Address address) { 26 this.address = address; 27 } 28 29 private Integer id; 30 private int age; 31 private String name; 32 private Address address; 33 34 }
Address是一个独立的实体,
1 package map.six11; 2 3 public class Address { 4 private Integer addressId; 5 private String addressDetail; 6 public Integer getAddressId() { 7 return addressId; 8 } 9 public void setAddressId(Integer addressId) { 10 this.addressId = addressId; 11 } 12 public String getAddressDetail() { 13 return addressDetail; 14 } 15 public void setAddressDetail(String addressDetail) { 16 this.addressDetail = addressDetail; 17 } 18 public Address() {} 19 public Address(String addressDetail) { 20 this.addressDetail = addressDetail; 21 } 22 }
在N的一端person实体的映射文件中,用<many-to-one>标签标识关联的属性实体address。
值得注意的是 cascade="all" 这个属性,当实体类有数据更新时,关联的属性类也会更新到数据库,这叫级联行为。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 5 <hibernate-mapping package="map.six11"> 6 <class name="Person" table="person_inf"> 7 <id name="id" column="person_id" type="int"> 8 <generator class="identity" /> 9 </id> 10 <property name="age" type="int" /> 11 <property name="name" type="string" /> 12 <many-to-one name="address" cascade="all" class="Address" column="address_id" /> 13 </class> 14 </hibernate-mapping>
在1的一端,则是一个普通的映射文件,
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 5 <hibernate-mapping package="map.six11"> 6 <class name="Address" table="address_inf"> 7 <id name="addressId" column="address_id"> 8 <generator class="identity" /> 9 </id> 10 <property name="addressDetail" /> 11 </class> 12 </hibernate-mapping>
下面是一个测试类,
1 package map.six11; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.Transaction; 6 import org.hibernate.cfg.Configuration; 7 8 public class PersonManager { 9 public static void testPerson() { 10 Configuration conf = new Configuration().configure(); 11 //conf.addResource("map.six11/Person.hbm.xml"); 12 conf.addClass(Person.class); 13 //conf.addResource("map.six11/Address.hbm.xml"); 14 conf.addClass(Address.class); 15 SessionFactory sf = conf.buildSessionFactory(); 16 Session sess = sf.openSession(); 17 Transaction tx = sess.beginTransaction(); 18 19 Person p = new Person(); 20 Address a = new Address("广州天河"); 21 p.setName("天王盖地虎"); 22 p.setAge(20); 23 p.setAddress(a); 24 sess.persist(p); 25 Address a2 = new Address("上海虹口"); 26 p.setAddress(a2); 27 28 tx.commit(); 29 sess.close(); 30 sf.close(); 31 } 32 33 public static void main(String[] args) { 34 testPerson(); 35 } 36 }
测试类中,Address只是一个瞬态的持久类,从未持久化,但是因为在Person实体类的映射文件中设置了cascade="all"属性,因此Address实体也会随着Person实体的更新而发生级联更新。
因此可以看到Hibernate不仅在Person表中插入了记录,而且还创建了Address表并且也插入了记录,hibernate日志如下,
1 Hibernate: insert into address_inf (addressDetail) values (?) 2 Hibernate: insert into person_inf (age, name, address_id) values (?, ?, ?) 3 Hibernate: insert into address_inf (addressDetail) values (?) 4 Hibernate: update person_inf set age=?, name=?, address_id=? where person_id=?
mysql数据如下,
person_inf

address_inf

表结构如下,person_inf表使用外键address_id与address_inf表关联,形成N-1的关联关系,address_inf表成为了主表。
address_inf表,

person_inf表,

原文:http://www.cnblogs.com/fysola/p/6252334.html