hibernate多对一和一对多关联
关联,是类的实例之间的关系,表示有意义和值得关注的连接。
多对一单向关联:
单向多对一:<many-to-one>定义一个持久化类与另一个持久化类的关联这种关联是数据表间的多对一关联,需要此持久化类映射表的外键引用另一个持久化类映射表的主键
many-to-one的一些属性:
update:进行update操作时是否包含此字段
insert:进行insert操作时是否包含此字段
update="false" insert="false" 意味着这格ClientChildType 无论何种情况,都不会被Hibernate 更新,新增,只有删除的时候,会影响到 ClientChildType,默认是true
name:映射类属性的名字
column:关联的字段
class:关联类的名字
cascade:设置操作中的级联策略 可选值为 all所有操作情况均进行级联、none所有操作情况均不进行级联、save-update执行save和update操作时级联、delete执行删除操作时级联
fetch:设置抓取数据的策略 默认值为select序列选择抓取 可选值为join外连接抓取
property-ref:指定关联类的一个属性,这个属性将会和本类的外键相对应(当外键参照一键时需要指定改属性)
双向多对一:hibernate既可以通过主控方实体加载被控方实体同时也可以通过被控方实体加载主控方实体。也就是说在单向一对多基础上,在被控方配置与主控方对应的对多一关系
在主键为对方外键表的持久化类中多了一个控方的Set集合
想要在hashset中进行排序的话,只需要在set标签内添加属性order by并赋值即可:
<set name="products" inverse="true" order by="id desc">
<key column="FACTORY"/>
<one-to-many class="com.hibernate.bean.Product"/>
</set>
有关sql:
product表与factory表:
create table Product( id int primary key auto_increment, name varchar(200) not null, price double null, factory int , FOREIGN KEY(factory) REFERENCES factory(factoryid) ) create table factory( factoryid int primary key auto_increment, factoryname varchar(200) not null )
Factory.java和Product.java与它们的hmb.xml
package com.hibernate.bean; public class Factory { private int factoryid; private String factoryname; public int getFactoryid() { return factoryid; } public void setFactoryid(int factoryid) { this.factoryid = factoryid; } public String getFactoryname() { return factoryname; } public void setFactoryname(String factoryname) { this.factoryname = factoryname; } public Factory(int factoryid, String factoryname) { super(); this.factoryid = factoryid; this.factoryname = factoryname; } public Factory(){} }
<class table="FACTORY" name="com.hibernate.bean.Factory" > <id name="factoryid" type="int"> <column name="FACTORYID"></column> <generator class="identity"></generator> </id> <property name="factoryname" type="string"> <column name="FACTORYNAME"/> </property> </class>
package com.hibernate.bean; public class Product { private int id; private String name; private double price; private Factory factory; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public Factory getFactory() { return factory; } public void setFactory(Factory factory) { this.factory = factory; } public Product(){} public Product(int id, String name, double price, Factory factory) { super(); this.id = id; this.name = name; this.price = price; this.factory = factory; } }
<class table="PRODUCT" name="com.hibernate.bean.Product" > <id name="id" type="int"> <column name="ID"></column> <generator class="identity"></generator> </id> <property name="name" type="string"> <column name="NAME"/> </property> <property name="price" type="double"> <column name="PRICE"/> </property> <!--<property name="factory" type="int"> <column name="FACTORY"/> </property> --> <many-to-one name="factory" class="com.hibernate.bean.Factory"> <column name="FACTORY"/> </many-to-one> </class>
测试:
public static void main(String[] args){ Session session=HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); Product p=(Product)session.get(Product.class, 1); System.out.println( "产品名称:"+p.getName()+"\t" +"产品价格:"+p.getPrice()+"\t" +"生产商:"+p.getFactory().getFactoryname()); }
结果:
注意:
在Product.java中的Factory不是数据表中的Factory字段,是一个Factory类对象。
<many-to-one> name属性填写持久化类中的字段名,class属性填写从表对应的持久化类名,相当于<property>中的type属性,<column>中name填写数据表中的对应字段也就是外键的字段
one-to-many:
就是前面的双向配置多对一的与单向的区别部分:
demo:
factory类增加Set的products属性以及其gettersetter方法 private Set<Product> products; public void setProducts(Set<Product> products) { this.products = products; } public Set<Product> getProducts() { return products; } ......
<set name="products" inverse="true"> <!--inserse=true意思是改变 该类的该set集合放弃对关联关系的维护权, 改变set中的内容,在factory类中的update和insert操作不影响数据库,个人表示这是正确的,因为在附表中的set集合本来就是虚构的一个字段,所以里面元素的改变不应该影响数据库中的改变-->
<key column="FACTORY"/>
<!--注意:column的值是主表的外键名而不是映射文件对应表的主键名-->
<one-to-many class="com.hibernate.bean.Product"/>
</set>
public static void main(String[] args){ Session session=HibernateUtil.getSessionFactory().openSession(); Transaction tx=session.beginTransaction(); Factory f=(Factory)session.get(Factory.class, 1); System.out.println("编号:"+f.getFactoryid()+"\t名称:"+f.getFactoryname()); Set<Product> s=f.getProducts(); Iterator<Product> it=s.iterator(); System.out.println("该工厂生产的商品:"); while(it.hasNext()){ Product p=it.next(); System.out.println(p.getName()+"\t"+p.getPrice()+"元"); } tx.commit(); }
结果: