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