Hibernate的多对一和一对多操作实例

供稿:hz-xin.com     日期:2025-01-14

  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



hibernate二级缓存什么时候用
1)一对多(<set><list>) ,在1的这方,通过1条sql查找得到了1个对象,由于关联的存在 ,那么又需要将这个对象关联的集合取出,所以合集数量是n还要发出n条sql,于是本来的1条sql查询变成了1 +n条 。 2)多对一<many-to-one> ,在多的这方,通过1条sql查询得到了n个对象,由于关联的存在,也会将这n个对象对应的...

JAVA Hibernate工作原理及为什么要用
2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。