论坛首页 Java企业应用论坛

Hibernate关系映射

浏览 2683 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-06-09  
组件映射
Xdoclet对组件的映射是这样写的
Customer.java
	/**
	 * @hibernate.component
	 * class="pojo.Address"
	 */
private Address address;

Address.java不需要映射class,因为address只是Customer的属性,是值类型,不是实体类型。
	/**
	 * @hibernate.property
	 * column="home_Address"
	 */
	private String homeAddress;
	/**
	 * @hibernate.property
	 * column="com_Address"
	 */
	private String comAddress;

在Customer.hbm.xml会生成
    <component name="address" class="pojo.Address">
      <property name="homeAddress" column="home_Address"/>
      <property name="comAddress" column="com_Address"/>
    </component>

在数据库中,T_Customer会生成home_Address和com_Address字段
One-to-one外键关联
Customer.java
	/**
	 * @hibernate.many-to-one
	 * unique="true"
	 * cascade="save-update"
	 */
	private Address address;

生成映射文件
<many-to-one unique="true" name="address" cascade="save-update"/>
即在T_Customer表中设置T_Address的外键

Address.java
	/**
	 * @hibernate.one-to-one
	 * 	class="pojo.Customer"
	 *  property-ref="address"
	 */
	private Customer customer;

生成映射文件
<one-to-one name="customer" property-ref="address" class="pojo.Customer"/>
property-ref="address"指定外键
测试:
CustomerManagerImpl m=new CustomerManagerImpl();
		Customer c=new Customer();
		c.setName("大大");
		c.setData(new Date());
		Address ads=new Address();
		ads.setComAddress("五一路");
		ads.setHomeAddress("五四路");
		c.setAddress(ads);
		m.addCustomer(c);

Many-to-One双向关联
Customer.java
/**
 * @author Administrator
 *@hibernate.class
 *	table=T_Customer
 */
public class Customer {
	/**
	 * @hibernate.id
	 * column="cid"
	 * 	generator-class="native"
	 */
	private int id;

	/**
	 * @hibernate.property
	 *  column="name"
	 */
	private String name;
	/**
	 * @hibernate.property
	 *  column="data"
	 */
	private Date data;
	/**
	 * @hibernate.set
	 * inverse="true"
	 * cascade="save-update"
	 * @hibernate.key
	 * column="customer"
	 * @hibernate.one-to-many
	 * class="pojo.Address"
	 */
	private Set address=new HashSet();
}


Address.java
/**
 *@hibernate.class
 *	table=T_Address
 */
public class Address {
	/**
	 * @hibernate.id
	 * 	column="aid"
	 * 	generator-class="native"
	 */
	private int id;
	/**
	 * @hibernate.property
	 *  column="address"
	 */
	private String address;
	/**
	 * 
	 * @hibernate.many-to-one
	 * 	class="pojo.Customer"
	 *  
	 */
	private Customer customer;
}

测试:
CustomerManagerImpl m=new CustomerManagerImpl();
	public void testAddCustomer() {
		Customer c=new Customer();
		c.setData(new Date());
		c.setName("李世民");
		Address a1=new Address();
		a1.setAddress("五台山");
		Address a2=new Address();
		a2.setAddress("长白山");		
		c.getAddress().add(a1);
		c.getAddress().add(a2);
		m.addCustomer(c);
	}

当set中没有设置Inverse=true时(主控在Customer方),执行如下sql
Hibernate: insert into T_Customer (name, data) values (?, ?)
Hibernate: insert into T_Address (address, customer) values (?, ?)
Hibernate: insert into T_Address (address, customer) values (?, ?)
Hibernate: update T_Address set customer=? where aid=?
Hibernate: update T_Address set customer=? where aid=?
设置inverse=true时(主控在Address方),执行如下sql
Hibernate: insert into T_Customer (name, data) values (?, ?)
Hibernate: insert into T_Address (address, customer) values (?, ?)
Hibernate: insert into T_Address (address, customer) values (?, ?)少了两条update语句
看表的结构
mysql> desc t_address;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| aid      | int(11)      | NO   | PRI | NULL    | auto_increment |
| address  | varchar(255) | YES  |     | NULL    |                |
| customer | int(11)      | YES  | MUL | NULL    |                |
+----------+--------------+------+-----+---------+----------------+
mysql> desc t_customer;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| cid   | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255) | YES  |     | NULL    |                |
| data  | datetime     | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
在t_address中有个外键指向t_customer,因为这个外键在表t_address中,如果主控方是Customer,那么当commit时Hibernate清理缓存,探测到Customer,和Address均有变化,这时Customer无法知道Address的状态,所以为了保证同步更新数据库,额外执行了两条update语句。假如主控方在Address,那么Address可以知道自己的状态,并通过外键也可以知道Customer的状态,所以无须做额外的更新。这对提高数据库的性能有很大的帮助。以上是我对inverse的理解,如有错误还请指正。
Many-to-Many双向关联
Bank.java
	/**
	 * @hibernate.set
	 * table="T_Bank_Customer"
	 * inverse="true"
	 * @hibernate.key
	 * column="bid"
	 * @hibernate.many-to-many
	 * column="cid"
	 * class="pojo.Customer"
	 */
	private Set customers=new HashSet();


Customer.java
	/**
	 *@hibernate.set
	 *	table="T_Bank_Customer"
	 *	cascade="all"
	 *@hibernate.key
	 *	column="cid"
	 *@hibernate.many-to-many
	 *	column="bid"
	 *	class="pojo.Bank"	
	 */
	private Set band=new HashSet();


测试:
	CustomerManagerImpl m=new CustomerManagerImpl();
	public void testAddCustomer() {
		Bank b=new Bank();
		b.setName("中国银行");
		Customer c=new Customer();
		c.setData(new Date());
		c.setName("黄骅");
		b.getCustomers().add(c);
		c.getBand().add(b);
		m.addCustomer(c);
	}

Inverse在哪一方设置为tru都会执行如下sql:
Hibernate: insert into T_Customer (name, data) values (?, ?)
Hibernate: insert into T_Bank (name) values (?)
Hibernate: insert into T_Bank_Customer (bid, cid) values (?, ?)
如果两边都没有设置inferse则默认为false那么两边都管理,导致混乱报异常。如果两都设置为true则会导致任何操作都不触发对关系表的操作,两表的数据添加了,但连接表为空,说明关系没有建立。
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics