Hibernate一对多数据关联。指的是单向一对多数据关联一个用户有多个地址,在用户类TUser中包含地址类TAddress集合。
Hibernate如果上手了,那么所谓的一对多,多对一,多对多,一对一这些关系,应该很快能理解.下面主要介绍Hibernate一对多的问题。
1.由TUser对象将自身的id赋给addr.user_id,这样导致addr属性值变动,在事物提交的时候,会进行update。
1)当save该用户的时候,
- insert into t_address (user_id, address, zipcode, tel) value (null, "HongKong", "233123", "1123")
2)当tx.commit()时:
- update t_address user_id="1", address="HongKong", zipcode="233123",tel="1123" where id=2;
这样,在save user时,就会出现约束违例。
调整方法:
可以在定义数据表字段时候,不加NOT NULL约束。或者在开始为user_id随意赋一个非空值(因为还要update,不正确也没关系),或者将user_id字段从TAddress.hbm.xml中删除(本例就是这样实现)。但是这些都是权宜之计,用两条SQL语句完成一次数据库操作,性能低下。而双向一对多解决了这个问题。
下面来实现双向关联:修改配置文件 TUser.hbm.xml
- xml version="1.0"?>
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="cn.blogjava.start.TUser" table="T_User" catalog="sample"
- dynamic-update="true" dynamic-insert="true"
- >
- <id name="id" type="integer">
- <column name="id" />
- <generator class="native" />
- < SPAN>id>
- <property name="name" type="string" column="name" />
- <property name="age" type="java.lang.Integer" column="age" />
- <set
- name="address"
- table="t_address"
- inverse="true"
- cascade="all"
- order-by="zipcode asc"
- >
- <key column="user_id">
- < SPAN>key>
- <one-to-many class="cn.blogjava.start.TAddress" />
- < SPAN>set>
- < SPAN>class>
- < SPAN>hibernate-mapping>
设定inverse="true",表明将TUser类作为被动类,将数据关联的维护工作交给关联对象TAddress来管理。
在one-to-many模型中,将many一方设为主控方有助于性能的改善。(让总理记住每个人困难,但是每个人记住总理方便)
TAddress.hbm.xml
- xml version="1.0"?>
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="cn.blogjava.start.TAddress" table="T_Address" catalog="sample">
- <id name="id" type="integer">
- <column name="id" />
- <generator class="native" />
- < SPAN>id>
- <property name="address" type="string" column="address" />
- <property name="zipcode" type="string" column="zipcode" />
- <property name="tel" type="string" column="tel" />
- <property name="type" type="string" column="type" />
- <property name="idx" type="java.lang.Integer" column="idx" />
- <many-to-one
- name="user"
- class="cn.blogjava.start.TUser"
- cascade="none"
- outer-join="auto"
- update="true"
- insert="true"
- access="property"
- column="user_id"
- not-null="true"
- />
- < SPAN>class>
- < SPAN>hibernate-mapping>
2.对TAddress.java做如下改造:去掉user_id字段,增加user字段,和getter,setter方法。
- package cn.blogjava.start;
- import java.io.Serializable;
- public class TAddress implements Serializable {
- private Integer id;
- private String address;
- private String zipcode;
- private String tel;
- private String type;
- private Integer idx;
- private TUser user;
- public TUser getUser() {
- return user;
- }
- public void setUser(TUser user) {
- this.user = user;
- }
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getAddress() {
- return address;
- }
- public void setAddress(String address) {
- this.address = address;
- }
- public Integer getIdx() {
- return idx;
- }
- public void setIdx(Integer idx) {
- this.idx = idx;
- }
- public String getTel() {
- return tel;
- }
- public void setTel(String tel) {
- this.tel = tel;
- }
- public String getType() {
- return type;
- }
- public void setType(String type) {
- this.type = type;
- }
- public String getZipcode() {
- return zipcode;
- }
- public void setZipcode(String zipcode) {
- this.zipcode = zipcode;
- }
- }
3.测试代码
既然TUser不维护关联关系,需要TAddress需要自己来维护TUser,所以需要addr.setUser(user);
- package cn.blogjava.start;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.List;
- import junit.framework.Assert;
- import junit.framework.TestCase;
- import org.hibernate.HibernateException;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.Transaction;
- import org.hibernate.cfg.Configuration;
- public class HibernateTest extends TestCase {
- Session session = null;
- protected void setUp() {
- try {
- Configuration config = new Configuration().configure();
- SessionFactory sessionFactory = config.buildSessionFactory();
- session = sessionFactory.openSession();
- } catch (HibernateException e) {
- e.printStackTrace();
- }
- }
- protected void tearDown() {
- try {
- session.close();
- } catch (HibernateException e) {
- e.printStackTrace();
- }
- }
- /** *//**
- * 对象持久化测试(Insert方法)
- */
- public void testInsert() {
- Transaction tran = null;
- try {
- TUser user = new TUser();
- user.setName("byf");
- user.setAge(new Integer(26));
- TAddress addr = new TAddress();
- addr.setTel("1123");
- addr.setZipcode("233123");
- addr.setAddress("HongKong");
- addr.setUser(user);
- TAddress addr2 = new TAddress();
- addr2.setTel("139");
- addr2.setZipcode("116001");
- addr2.setAddress("dalian");
- addr2.setUser(user);
- TAddress addr3 = new TAddress();
- addr3.setTel("136");
- addr3.setZipcode("100080");
- addr3.setAddress("beijing");
- addr3.setUser(user);
- //设置关联
- HashSet set = new HashSet();
- set.add(addr);
- set.add(addr2);
- set.add(addr3);
- user.setAddress(set);
- tran = session.beginTransaction();
- //插入user信息
- session.save(user);
- session.flush();
- tran.commit();
- Assert.assertEquals(user.getId().intValue()>0 ,true);
- } catch (HibernateException e) {
- e.printStackTrace();
- Assert.fail(e.getMessage());
- if(tran != null) {
- try {
- tran.rollback();
- } catch (Exception e1) {
- e1.printStackTrace();
- }
- }
- }
- }
- /** *//**
- * 对象读取测试(Select方法)
- */
- public void testSelect(){
- String hql = " from TUser where name='byf'";
- try {
- List userList = session.createQuery(hql).list();
- TUser user = (TUser)userList.get(0);
- System.out.println("user name is " + user.getName());
- for (Iterator iter = user.getAddress().iterator(); iter.hasNext();) {
- TAddress addr = (TAddress) iter.next();
- System.out.println("user address is " + addr.getAddress());
- }
- Assert.assertEquals(user.getName(), "byf");
- } catch (Exception e) {
- e.printStackTrace();
- Assert.fail(e.getMessage());
- }
- }
- }
以上介绍Hibernate一对多数据关联。
【编辑推荐】