Hibernate和JPA使用连接表处理多对一映射

本文介绍如何使用JPA和Hibernate实现多对一及多对多的关系映射,包括实体类定义与配置文件详解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在项目中,原有的持久化操作时使用JPA进行的,通过注解多对一映射被映射成中间表和两个数据库表,其代码如下:

  1. importjavax.persistence.Column;
  2. importjavax.persistence.Entity;
  3. importjavax.persistence.GeneratedValue;
  4. importjavax.persistence.GenerationType;
  5. importjavax.persistence.Id;
  6. importjavax.persistence.NamedQueries;
  7. importjavax.persistence.NamedQuery;
  8. importjavax.persistence.Table;
  9. /**
  10. *产品实体类
  11. *@author李文锴
  12. */
  13. @Entity
  14. @Table(name="yunda_product")
  15. @NamedQueries({
  16. @NamedQuery(name="getProduct",query="SELECTpFROMOrderProductASp"),
  17. @NamedQuery(name="getProductByName",query="SELECTpFROMOrderProductASpWHEREp.name=:name")
  18. })
  19. publicclassOrderProductimplementsjava.io.Serializable{
  20. privatestaticfinallongserialVersionUID=1L;
  21. /**
  22. *货物id
  23. */
  24. @Id
  25. @GeneratedValue(strategy=GenerationType.AUTO)
  26. privateLongid;
  27. /**
  28. *货物名称
  29. */
  30. @Column(name="p_name",length=80,nullable=false)
  31. privateStringname;
  32. /**
  33. *货物类型
  34. */
  35. @Column(name="p_type",length=80,nullable=false)
  36. privateStringtype;
  37. /**
  38. *货物数量
  39. */
  40. @Column(name="p_quantity",nullable=false)
  41. privateintquantity;
  42. publicOrderProduct(){
  43. }
  44. publicOrderProduct(Stringname,Stringtype,intquantity){
  45. setName(name);
  46. setType(type);
  47. setQuantity(quantity);
  48. }
  49. publicLonggetId(){
  50. returnid;
  51. }
  52. publicvoidsetId(Longid){
  53. this.id=id;
  54. }
  55. publicStringgetName(){
  56. returnname;
  57. }
  58. publicvoidsetName(Stringname){
  59. this.name=name;
  60. }
  61. publicintgetQuantity(){
  62. returnquantity;
  63. }
  64. publicvoidsetQuantity(intquantity){
  65. this.quantity=quantity;
  66. }
  67. publicStringgetType(){
  68. returntype;
  69. }
  70. publicvoidsetType(Stringtype){
  71. this.type=type;
  72. }
  73. @Override
  74. publicbooleanequals(Objectobj){
  75. if(obj==null){
  76. returnfalse;
  77. }
  78. if(getClass()!=obj.getClass()){
  79. returnfalse;
  80. }
  81. finalOrderProductother=(OrderProduct)obj;
  82. if((this.name==null)?(other.name!=null):!this.name.equals(other.name)){
  83. returnfalse;
  84. }
  85. if((this.type==null)?(other.type!=null):!this.type.equals(other.type)){
  86. returnfalse;
  87. }
  88. if(this.quantity!=other.quantity){
  89. returnfalse;
  90. }
  91. returntrue;
  92. }
  93. @Override
  94. publicinthashCode(){
  95. inthash=7;
  96. hash=61*hash+(this.name!=null?this.name.hashCode():0);
  97. hash=61*hash+(this.type!=null?this.type.hashCode():0);
  98. hash=61*hash+this.quantity;
  99. returnhash;
  100. }
  101. }

  1. importjava.util.Date;
  2. importjava.util.Set;
  3. importjavax.persistence.CascadeType;
  4. importjavax.persistence.Column;
  5. importjavax.persistence.Entity;
  6. importjavax.persistence.GeneratedValue;
  7. importjavax.persistence.GenerationType;
  8. importjavax.persistence.Id;
  9. importjavax.persistence.JoinColumn;
  10. importjavax.persistence.JoinTable;
  11. importjavax.persistence.OneToMany;
  12. importjavax.persistence.Table;
  13. importjavax.persistence.Temporal;
  14. /**
  15. *存储订单实体类,其中和产品实体进行关联
  16. *@author李文锴
  17. */
  18. @Entity
  19. @Table(name="stock_order")
  20. publicclassStockOrderimplementsjava.io.Serializable{
  21. privatestaticfinallongserialVersionUID=1L;
  22. /**
  23. *订单id
  24. */
  25. @Id
  26. @GeneratedValue(strategy=GenerationType.AUTO)
  27. privateLongid;
  28. /**
  29. *客户编号
  30. */
  31. @Column(name="customer_no",length=20,nullable=false)
  32. privateStringcustomerNO;
  33. /**
  34. *客户名称
  35. */
  36. @Column(name="customer_name",length=80,nullable=false)
  37. privateStringcustomerName;
  38. /**
  39. *产品
  40. */
  41. @OneToMany(cascade=CascadeType.ALL)
  42. @JoinTable(name="stock_order_product",joinColumns={@JoinColumn(name="stock_order_id")},inverseJoinColumns={@JoinColumn(name="product_id")})
  43. privateSet<OrderProduct>prdoucts;
  44. /**
  45. *到达日期
  46. */
  47. @Column(name="arrival_date",nullable=false)
  48. @Temporal(javax.persistence.TemporalType.DATE)
  49. privateDatearrivalDate;
  50. publicStockOrder(){
  51. }
  52. publicStockOrder(StringcustomerNO,StringcustomerName,Set<OrderProduct>prdoucts,DatearrivalDate){
  53. setCustomerNO(customerNO);
  54. setCustomerName(customerName);
  55. setPrdoucts(prdoucts);
  56. setArrivalDate(arrivalDate);
  57. }
  58. publicDategetArrivalDate(){
  59. returnarrivalDate;
  60. }
  61. publicvoidsetArrivalDate(DatearrivalDate){
  62. this.arrivalDate=arrivalDate;
  63. }
  64. publicStringgetCustomerNO(){
  65. returncustomerNO;
  66. }
  67. publicvoidsetCustomerNO(StringcustomerNO){
  68. this.customerNO=customerNO;
  69. }
  70. publicLonggetId(){
  71. returnid;
  72. }
  73. publicvoidsetId(Longid){
  74. this.id=id;
  75. }
  76. publicSet<OrderProduct>getPrdoucts(){
  77. returnprdoucts;
  78. }
  79. publicvoidsetPrdoucts(Set<OrderProduct>prdoucts){
  80. this.prdoucts=prdoucts;
  81. }
  82. publicStringgetCustomerName(){
  83. returncustomerName;
  84. }
  85. publicvoidsetCustomerName(StringcustomerName){
  86. this.customerName=customerName;
  87. }
  88. @Override
  89. publicbooleanequals(Objectobj){
  90. if(obj==null){
  91. returnfalse;
  92. }
  93. if(getClass()!=obj.getClass()){
  94. returnfalse;
  95. }
  96. finalStockOrderother=(StockOrder)obj;
  97. if((this.customerNO==null)?(other.customerNO!=null):!this.customerNO.equals(other.customerNO)){
  98. returnfalse;
  99. }
  100. if((this.customerName==null)?(other.customerName!=null):!this.customerName.equals(other.customerName)){
  101. returnfalse;
  102. }
  103. if(this.prdoucts!=other.prdoucts&&(this.prdoucts==null||!this.prdoucts.equals(other.prdoucts))){
  104. returnfalse;
  105. }
  106. if(this.arrivalDate!=other.arrivalDate&&(this.arrivalDate==null||!this.arrivalDate.equals(other.arrivalDate))){
  107. returnfalse;
  108. }
  109. returntrue;
  110. }
  111. @Override
  112. publicinthashCode(){
  113. inthash=5;
  114. hash=59*hash+(this.customerNO!=null?this.customerNO.hashCode():0);
  115. hash=59*hash+(this.customerName!=null?this.customerName.hashCode():0);
  116. hash=59*hash+(this.prdoucts!=null?this.prdoucts.hashCode():0);
  117. hash=59*hash+(this.arrivalDate!=null?this.arrivalDate.hashCode():0);
  118. returnhash;
  119. }
  120. }
  1. importjava.util.Date;
  2. importjava.util.Set;
  3. importjavax.persistence.CascadeType;
  4. importjavax.persistence.Column;
  5. importjavax.persistence.Entity;
  6. importjavax.persistence.GeneratedValue;
  7. importjavax.persistence.GenerationType;
  8. importjavax.persistence.Id;
  9. importjavax.persistence.JoinColumn;
  10. importjavax.persistence.JoinTable;
  11. importjavax.persistence.OneToMany;
  12. importjavax.persistence.Table;
  13. importjavax.persistence.Temporal;
  14. /**
  15. *运输订单实体类,并于产品实体进行关联
  16. *@author李文锴
  17. */
  18. @Entity
  19. @Table(name="trans_order")
  20. publicclassTransOrderimplementsjava.io.Serializable{
  21. privatestaticfinallongserialVersionUID=1L;
  22. /**
  23. *订单id
  24. */
  25. @Id
  26. @GeneratedValue(strategy=GenerationType.AUTO)
  27. privateLongid;
  28. /**
  29. *客户编号
  30. */
  31. @Column(name="customer_no",length=20,nullable=false)
  32. privateStringcustomerNO;
  33. /**
  34. *客户名称
  35. */
  36. @Column(name="customer_name",length=80,nullable=false)
  37. privateStringcustomerName;
  38. /**
  39. *产品
  40. */
  41. @OneToMany(cascade=CascadeType.ALL)
  42. @JoinTable(name="trans_order_product",joinColumns={@JoinColumn(name="trans_order_id")},inverseJoinColumns={@JoinColumn(name="product_id")})
  43. privateSet<OrderProduct>prdoucts;
  44. /**
  45. *其实地址
  46. */
  47. @Column(name="start_address",length=80,nullable=false)
  48. privateStringstartAddress;
  49. /**
  50. *目的地址
  51. */
  52. @Column(name="end_address",length=80,nullable=false)
  53. privateStringendAddress;
  54. /**
  55. *运输日期
  56. */
  57. @Column(name="trans_date",nullable=false)
  58. @Temporal(javax.persistence.TemporalType.DATE)
  59. privateDatetransportationDate;
  60. publicTransOrder(){
  61. }
  62. publicTransOrder(StringcustomerNO,StringcustomerName,Set<OrderProduct>prdoucts,StringstartAddress,StringendAddress,DatetransportationDate){
  63. setCustomerNO(customerNO);
  64. setCustomerName(customerName);
  65. setPrdoucts(prdoucts);
  66. setStartAddress(startAddress);
  67. setEndAddress(endAddress);
  68. setTransportationDate(transportationDate);
  69. }
  70. publicDategetTransportationDate(){
  71. returntransportationDate;
  72. }
  73. publicvoidsetTransportationDate(DatetransportationDate){
  74. this.transportationDate=transportationDate;
  75. }
  76. publicStringgetCustomerNO(){
  77. returncustomerNO;
  78. }
  79. publicvoidsetCustomerNO(StringcustomerNO){
  80. this.customerNO=customerNO;
  81. }
  82. publicLonggetId(){
  83. returnid;
  84. }
  85. publicvoidsetId(Longid){
  86. this.id=id;
  87. }
  88. publicSet<OrderProduct>getPrdoucts(){
  89. returnprdoucts;
  90. }
  91. publicvoidsetPrdoucts(Set<OrderProduct>prdoucts){
  92. this.prdoucts=prdoucts;
  93. }
  94. publicStringgetCustomerName(){
  95. returncustomerName;
  96. }
  97. publicvoidsetCustomerName(StringcustomerName){
  98. this.customerName=customerName;
  99. }
  100. publicStringgetEndAddress(){
  101. returnendAddress;
  102. }
  103. publicvoidsetEndAddress(StringendAddress){
  104. this.endAddress=endAddress;
  105. }
  106. publicStringgetStartAddress(){
  107. returnstartAddress;
  108. }
  109. publicvoidsetStartAddress(StringstartAddress){
  110. this.startAddress=startAddress;
  111. }
  112. @Override
  113. publicbooleanequals(Objectobj){
  114. if(obj==null){
  115. returnfalse;
  116. }
  117. if(getClass()!=obj.getClass()){
  118. returnfalse;
  119. }
  120. finalTransOrderother=(TransOrder)obj;
  121. if((this.customerNO==null)?(other.customerNO!=null):!this.customerNO.equals(other.customerNO)){
  122. returnfalse;
  123. }
  124. if((this.customerName==null)?(other.customerName!=null):!this.customerName.equals(other.customerName)){
  125. returnfalse;
  126. }
  127. if(this.prdoucts!=other.prdoucts&&(this.prdoucts==null||!this.prdoucts.equals(other.prdoucts))){
  128. returnfalse;
  129. }
  130. if((this.startAddress==null)?(other.startAddress!=null):!this.startAddress.equals(other.startAddress)){
  131. returnfalse;
  132. }
  133. if((this.endAddress==null)?(other.endAddress!=null):!this.endAddress.equals(other.endAddress)){
  134. returnfalse;
  135. }
  136. if(this.transportationDate!=other.transportationDate&&(this.transportationDate==null||!this.transportationDate.equals(other.transportationDate))){
  137. returnfalse;
  138. }
  139. returntrue;
  140. }
  141. @Override
  142. publicinthashCode(){
  143. inthash=3;
  144. hash=79*hash+(this.customerNO!=null?this.customerNO.hashCode():0);
  145. hash=79*hash+(this.customerName!=null?this.customerName.hashCode():0);
  146. hash=79*hash+(this.prdoucts!=null?this.prdoucts.hashCode():0);
  147. hash=79*hash+(this.startAddress!=null?this.startAddress.hashCode():0);
  148. hash=79*hash+(this.endAddress!=null?this.endAddress.hashCode():0);
  149. hash=79*hash+(this.transportationDate!=null?this.transportationDate.hashCode():0);
  150. returnhash;
  151. }
  152. }

先要使用Hibernate对其进行映射,由于产生了中间表,所以它的配置文件有些不同,如下:

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  3. <hibernate-mapping>
  4. <classname="com.yunda.dao.domain.Product"table="yunda_product">
  5. <idname="id"type="long">
  6. <generatorclass="native"/>
  7. </id>
  8. <propertyname="name"column="p_name"type="string"length="80"not-null="true"/>
  9. <propertyname="type"column="p_type"type="string"length="80"not-null="true"/>
  10. <propertyname="quantity"column="p_quantity"type="integer"length="80"not-null="true"/>
  11. <!--使用join来配置多对一的连接,以table属性来表示连接表的多对一,连接表为stock_order_id-->
  12. <!--optional属性表示这是一个外连接,inverse属性可以出现在一端和多端,这里选择出现在多端,效果相同-->
  13. <jointable="stock_order_product"optional="true"inverse="true">
  14. <!--该key的字段为连接表中的字段,作为外键-->
  15. <keycolumn="product_id"/>
  16. <!--连接表中配置多对一,对应的字段为stock_order_id-->
  17. <many-to-onename="stockOrder"column="stock_order_id"not-null="true"/>
  18. </join>
  19. <!--使用join来配置多对一的连接,以table属性来表示连接表的多对一,连接表为trans_order_id-->
  20. <!--optional属性表示这是一个外连接,inverse属性可以出现在一端和多端,这里选择出现在多端,效果相同-->
  21. <jointable="trans_order_product"optional="true"inverse="true">
  22. <!--该key的字段为连接表中的字段,作为外键-->
  23. <keycolumn="product_id"/>
  24. <!--连接表中配置多对一,对应的字段为trans_order_id-->
  25. <many-to-onename="transOrder"column="trans_order_id"not-null="true"/>
  26. </join>
  27. </class>
  28. </hibernate-mapping>

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  3. <hibernate-mapping>
  4. <classname="com.yunda.dao.domain.StockOrder"table="stock_order">
  5. <idname="id"type="long">
  6. <generatorclass="native"/>
  7. </id>
  8. <propertyname="customerNO"column="customer_no"type="string"length="20"not-null="true"/>
  9. <propertyname="customerName"column="customer_name"type="string"length="80"not-null="true"/>
  10. <propertyname="arrivalDate"column="arrival_date"type="date"not-null="true"/>
  11. <!--通过连接表的一端,因此需要table属性为stock_order_product-->
  12. <setname="prdoucts"cascade="all"table="stock_order_product"lazy="false">
  13. <!--该key的字段为连接表中的字段,作为外键-->
  14. <keycolumn="stock_order_id"/>
  15. <!--配置多对多-->
  16. <!--但是unique属性为true,表示product_id字段为不可重复,保证一对多关系-->
  17. <many-to-manyclass="com.yunda.dao.domain.Product"column="product_id"unique="true"/>
  18. </set>
  19. </class>
  20. </hibernate-mapping>

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  3. <hibernate-mapping>
  4. <classname="com.yunda.dao.domain.TransOrder"table="trans_order">
  5. <idname="id"type="long">
  6. <generatorclass="native"/>
  7. </id>
  8. <propertyname="customerNO"column="customer_no"type="string"length="20"not-null="true"/>
  9. <propertyname="customerName"column="customer_name"type="string"length="80"not-null="true"/>
  10. <propertyname="startAddress"column="start_address"type="string"length="80"not-null="true"/>
  11. <propertyname="endAddress"column="end_address"type="string"length="80"not-null="true"/>
  12. <propertyname="transportationDate"column="trans_date"type="date"not-null="true"/>
  13. <!--通过连接表的一端,因此需要table属性为stock_order_product-->
  14. <setname="prdoucts"cascade="all"table="trans_order_product"lazy="false">
  15. <!--该key的字段为连接表中的字段,作为外键-->
  16. <keycolumn="trans_order_id"/>
  17. <!--配置多对多-->
  18. <!--但是unique属性为true,表示product_id字段为不可重复,保证一对多关系-->
  19. <many-to-manyclass="com.yunda.dao.domain.Product"column="product_id"unique="true"/>
  20. </set>
  21. </class>
  22. </hibernate-mapping>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值