hibernate关系映射
注:(1)在项目开发中,经常遇到无法映射class的情况,所以最好在映射文件中将name和class的路径写完全。
(2)在1的数据表中不会出现set中的column,只会在n的一端的表中出现这个column字段。一、双向1-N关联
使用无连接表的1-N关联
1.Person.java
person是1,address是n。一个人对应多个地址,所以在person类中有一个address的set集合。
package com.ru.domain; import java.util.HashSet; import java.util.Set; public class Person { private Integer p_id; private String name; private Set<Address> address=new HashSet<Address>(); public Integer getP_id() { return p_id; } public void setP_id(Integer p_id) { this.p_id = p_id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Address> getAddress() { return address; } public void setAddress(Set<Address> address) { this.address = address; } }
2.Address.java
一个地址只对应一个人,所以用了一个person对象。
package com.ru.domain; public class Address { private Integer aid; private String addressname; private Person person; public Integer getAid() { return aid; } public void setAid(Integer aid) { this.aid = aid; } public String getAddressname() { return addressname; } public void setAddressname(String addressname) { this.addressname = addressname; } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } }
注:在持久化类的映射文件中,1的一方不会在数据表中显示集合,通常只需要在n的一端数据表里增加一个外键。
3.Person.hbm.xml
注意:set集合里面的column并不会在数据表中出现,而是在n的一方address的数据表中出现,并且这个值和many-to-one里面的column属性值必须相同。
key里的column指向address表中的外键
<?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> <class name="com.ru.domain.Person" table="person"> <id name="p_id" column="person_id" type="java.lang.Integer"> <generator class="native"/> </id> <property name="name" column="name" type="java.lang.String"></property> <!-- inverse=“true”是不控制关联关系 --> <set name="address" inverse="true"> <key column="person_id"></key> <one-to-many class="com.ru.domain.Address"/> </set> </class> </hibernate-mapping>
4.Address.hbm.xml
<?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> <class name="com.ru.domain.Address" table="address"> <id name="aid" column="id" type="java.lang.Integer"> <generator class="native"/> </id> <property name="addressname" column="addressname" type="java.lang.String"></property> <!-- 多对一个关联关系 --> <many-to-one name="person" column="person_id" class="com.ru.domain.Person"></many-to-one> </class> </hibernate-mapping>
5.testPerson.java
这个是service测试文件
package com.ru.service; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import com.ru.domain.Address; import com.ru.domain.Person; public class testPerson { public static void main(String[] args){ Configuration cf=new Configuration().configure("hibernate.cfg.xml"); SessionFactory sf=cf.buildSessionFactory(); Session s=sf.openSession(); Transaction ts=s.beginTransaction(); try { //人 Person p=new Person(); p.setName("如"); s.save(p); //p.setAddress(address); //第一个地址 Address a1=new Address(); a1.setAddressname("北京"); a1.setPerson(p); s.save(a1); //第二个地址 Address a2=new Address(); a2.setAddressname("天津"); a2.setPerson(p); s.save(a2); ts.commit(); s.close(); sf.close(); } catch (HibernateException e) { e.printStackTrace(); } } }
6.hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 配置mysql数据库 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/ru</property> <property name="connection.username">root</property> <property name="connection.password">123456</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 自动创建表 --> <property name="hbm2ddl.auto">create</property> <!-- 显示sql语句 --> <property name="show_sql">true</property> <!-- 如果使用getCurrentSession,必须配置下面的属性 --> <!-- <property name="hibernate.current_session_context_class">thread</property> --> <mapping resource="com/ru/domain/Person.hbm.xml"/> <mapping resource="com/ru/domain/Address.hbm.xml"/> </session-factory> </hibernate-configuration>
二、双向N-N映射
只能采用连接表来建立两个实体间的N-N关联关系。
1、Person.java
package com.ru.domain; import java.util.HashSet; import java.util.Set; public class Person { private Integer pid; private String name; //1-n关联关系,使用set保存关连实体 private Set<Address> address=new HashSet();
2.Address.java
package com.ru.domain; import java.util.Set; public class Address { private Integer aid; private String addressdetail; //同样1-n,记录person实体的属性 private Set<Person> person;
3.Person.hbm.xml
<?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> <class name="com.ru.domain.Person" table="person"> <id name="pid" column="pid" type="java.lang.Integer"> <generator class="identity"></generator> </id> <property name="name" column="name" type="java.lang.String"></property> <!--映射n-n关联实体,两边的table属性必须有且必须相同 --> <set name="address" table="p_a"> <!-- 这个key中的column对应的是address表中的外键字段--> <key column="p_id"></key> <!--映射到的关联类属性,这里的a_id会在person表的字段中--> <many-to-many class="com.ru.domain.Address" column="a_id"></many-to-many> </set> </class> </hibernate-mapping>
4,Address.hbm.xml
<?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> <class name="com.ru.domain.Address" > <id name="aid" column="aid" type="java.lang.Integer"> <generator class="identity"></generator> </id> <property name="addressdetail" column="addressdetail" type="java.lang.String"></property> <set name="person" table="p_a"> <key column="a_id"></key> <!--这里的p_id是address表中字段--> <many-to-many class="com.ru.domain.Person" column="p_id"></many-to-many> </set> </class> </hibernate-mapping>
5.test.java
package com.ru.service; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import com.ru.domain.Address; import com.ru.domain.Person; public class test1 { public static void main(String[] args) { Configuration cf=new Configuration().configure(); SessionFactory sf=cf.buildSessionFactory(); Session session=sf.getCurrentSession(); Transaction ts=session.beginTransaction(); try { //向person中添加一条记录 Person p1=new Person(); p1.setName("如"); session.save(p1); //向address中添加一条记录 Address a1=new Address(); a1.setAddressdetail("北京"); session.save(a1); //主外键关系 p1.getAddress().add(a1); //a1.getPerson().add(p1); ts.commit(); } catch (Exception e) { e.printStackTrace(); } } }
注:会产生三个表
三、双向1-1关联
第一种关联策略:主键关联
1.Person.java
package com.ru.domain; public class Person { private Integer id; private String name; //1-1关系 private IdCard idcard;
2.IdCard.java
package com.ru.domain; public class Person { private Integer id; private String name; //1-1关系 private IdCard idcard;
3.Person.hbm.xml
<?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> <class name="com.ru.domain.Person" table="person"> <id name="id" column="id"> <!--定义主键生成策略--> <generator class="identity"/> </id> <property name="name" column="name" type="java.lang.String"/> <!--映射关联实体--> <one-to-one name="idcard"></one-to-one> </class> </hibernate-mapping>
4.IdCard.hbm.xml
<?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> <class name="com.ru.domain.IdCard" table="IdCard"> <id name="id" column="id" type="java.lang.Integer"> <generator class="foreign"> <!-- 该实体的主键根据person属性引用的实体的主键生成 --> <param name="property">person</param> </generator> </id> <property name="CardNo" column="cardno" type="java.lang.String"></property> <one-to-one name="person"></one-to-one> </class> </hibernate-mapping>
5.test.java
package com.ru.service; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import com.ru.domain.IdCard; import com.ru.domain.Person; public class test1 { public static void main(String[] args) { Configuration cf=new Configuration().configure(); SessionFactory sf=cf.buildSessionFactory(); Session session=sf.getCurrentSession(); Transaction ts=session.beginTransaction(); try { //向person中添加一条记录 Person p1=new Person(); p1.setName("如"); session.save(p1); //idcard IdCard ic=new IdCard(); ic.setCardNo("1111"); //这个必须有不然idcard不能声称主键 ic.setPerson(p1); session.save(ic); //主外键关系 ts.commit(); } catch (Exception e) { e.printStackTrace(); } } }