Hibernate的多对一和一对多操作实例
Hibernate <>的一对多和多对一操作真的很方便 如果系统采用Hibernate作为持久层 完全可以把对应的一对多和多对一逻辑关系放在Hibernate里面控制 减少数据库的负担 而且也更清晰
多对一和一对多概念
其实这个概念上来说很简单 比如一个客户可以有多个订单 多个订单属于同一个客户 就是最基本的一对多 和多对一 数据库使用中 感觉多对一和一对多算是比较常见的逻辑关系了
我曾经做过一些数据库 比如某些 *** 部门的 其表单很设计的很简单粗糙 甚至连主键都没有 完全靠在事务层补全这些关系 其实通过Hibernate持久层来实现逻辑关系也是很不错的方法 下面的例子 就是数据库逻辑上基本没有定义 主要放在持久层里面 这个也主要是我对数据库操作属于半通水的原因
数据库层
这里面有两个表单 一个CUSTOMER 客户表单 一个是ORDERS 订单表单 生成客户表单 这个是在SQLServer里面做的 其实其他都一样 因为逻辑关系在Hibernate上面 id是主键非空 其他可以为空
CREATETABLE[dbo] [CUSTOMER](
[id][numeric]( )NOTNULL
[name][varchar]( )NULL
[age][int]NULL
CONSTRAINT[PK_CUSTOMER]PRIMARYKEY)
订单表单
id为主键非空 CUSTOMER_id是对应客户主键 也非空 这里不做外键设置
CREATETABLE[dbo] [ORDERS](
[id][numeric]( )NULLPRIMARYKEY
[CUSTOMER_id][numeric]( )NOTNULL
[ORDER_NUMBER][varchar]( )NULL
[PRICE][numeric]( )NULL
)
Hibernate设定
HIbernate里面 一对多的对象体现 是客户有一个集合set set里面放著对应订单 而多对一体现 是订单里面有一个CUSTOMER对象 表明该订单所属的客户 其中 CUSTOMER类为
publicclassCustomerimplementsjava io Serializable{
privateLongid;
privateStringname;
privateIntegerage;
privateSetrderses=newHashSet();
}
后面的getXXX和setXXX方法就省去了 同样订单类就是
publicclassOrdersimplementsjava io Serializable{
privateLongid;
privateCustomercustomer;
privateStringorderNumber;
privateDoubleprice;
}
而对应hbm文档 就是map文档如下
CUSTOMER hbm xml
<!DOCTYPEhibernate mappingPUBLIC //Hibernate/HibernateMappingDTD //EN
mapping dtd >
<!
MappingfileautogeneratedbyMyEclipsePersistenceTools
>
<hibernate mapping>
<classnameclassname= onetomany Customer table= CUSTOMER schema= dbo catalog= DBTEST >
<idnameidname= id type= java lang Long >
<columnnamecolumnname= id precision= scale= />
<generatorclassgeneratorclass= increment />
</id>
<propertynamepropertyname= name type= java lang String >
<columnnamecolumnname= name length= />
</property>
<propertynamepropertyname= age type= java lang Integer >
<columnnamecolumnname= age />
</property>
<setnamesetname= orderses inverse= true lazy= true cascade= all >
<key>
<columnnamecolumnname= CUSTOMER_id precision= scale= not null= true />
</key>
<one to manyclassone to manyclass= onetomany Orders />
</set>
</class>
</hibernate mapping>
这个里面 其他都很简答了 其中<generatorclass= increment />表示主键值自动增加 这个主要针对字符串对应的 主要体现多对以的是
<setnamesetname= orderses inverse= true lazy= true cascade= all >
<key>
<columnnamecolumnname= CUSTOMER_id precision= scale= not null= true />
</key>
<one to manyclassone to manyclass= onetomany Orders />
</set>
其中 set表示 对应集合 fetch和lazy主要是用来级联查询的 而cascade和inverse主要是用来级联插入和修改的 这几个主要包括对集合的控制 <one to manyclass= onetomany Orders />表示对应类 即set里面包含的类 而key主要是用于确定set里面对应表单列
ORDERS的hbm
<?xmlversionxmlversion= encoding= utf ?>
<!DOCTYPEhibernate mappingPUBLIC //Hibernate/HibernateMappingDTD //EN
mapping dtd >
<!
MappingfileautogeneratedbyMyEclipsePersistenceTools
>
<hibernate mapping>
<classcatalogclasscatalog= DBTEST name= onetomany Orders schema= dbo table= ORDERS >
<idnameidname= id type= java lang Long >
<columnnamecolumnname= id precision= scale= />
<generatorclassgeneratorclass= increment />
</id>
<many to oneclas *** any to oneclass= onetomany Customer fetch= select name= customer >
<columnnamecolumnname= CUSTOMER_id precision= scale= />
</many to one>
<propertygeneratedpropertygenerated= never lazy= false name= orderNumber type= java lang String >
<columnlengthcolumnlength= name= ORDER_NUMBER />
</property>
<propertygeneratedpropertygenerated= never lazy= false name= price type= java lang Double >
<columnnamecolumnname= PRICE precision= scale= />
</property>
</class>
</hibernate mapping>
<many to oneclas *** any to oneclass= onetomany Customer fetch= select name= customer >
<columnnamecolumnname= CUSTOMER_id precision= scale= />
</many to one>
表示CUSTOMER熟悉对应的类 和其作为key的列名 上面这些都可以在MyEclipse里面自动生成 另外注意的一点是 在生成的DAO里面 涉及表单操作的save()和delete()方法 必须要事件提交 数据库才有反映 可以就该Hibernate xml 或者用下面这样代码来实现
Sessionse=getSession();
Transactiontx=se beginTransaction();
se delete(persistentInstance);
//se save(instance);
mit();
验证效果
新增用户
如果新增一个用户 该用户里面包含有两个表单 那么 由于持久层已经实现了逻辑关系 只要用户类里面的set包含了表单 则表单可以自动增加 实现代码
CustomerDAOcd=newCustomerDAO();
Customerxd=newCustomer( 王小虎 null);
Ordersord =newOrders();
ord setCustomer(xd);
ord setOrderNumber( 王小虎的买单 );
Ordersord =newOrders();
ord setCustomer(xd);
ord setOrderNumber( 王小虎的买单 );
Setrderses=newHashSet();
orderses add(ord );
orderses add(ord );
xd setOrderses(orderses);
cd save(xd);
代码里面 加入一个王小虎用户 两个订单 通过setOrderses加入 只使用cd save这一个对持久层操作 完成后查询
王小虎
=================================
王小虎的买单
王小虎的买单
显示 CUSTOMER里面加入了王小虎 ORDERS里面也加入他的订单
删除操作
List<Customer>csList=cd findByProperty( name 王小虎 );
for(Customercs:csList){
cd delete(cs);
}
这个很简单了 通过其中findByProperty( name 王小虎 );对应SQL为deletefromtableCUSTOMERwherename= 王小虎 ;删除了王小虎 而ORDERS里面 王小虎对应的表单也同时被删除
小小总结
lishixinzhi/Article/program/Java/ky/201311/28543