组件映射
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则会导致任何操作都不触发对关系表的操作,两表的数据添加了,但连接表为空,说明关系没有建立。