Hibernate基於注解的雙向one-to-many映射關系的實現


背景:
一的一端:QingAoCenterInfo:青奧場所信息,
多的一端:QingAoPlaceInfo:青奧場館信息,
其中一個青奧場所下可以包含多個青奧場館

one端:QingAoCenterInfo,持有QingAoPlaceInfo的List引用,
通過注解@OneToMany(mappedBy="qingAoCenterInfo",cascade= CascadeType.ALL)

mappedBy:定義類之間的雙向關系。如果類之間是單向關系,不需要提供定義,如果類和類之間形成雙向關系,我們就需要使用這個屬性進行定義, 否則可能引起數據一致性的問題。要由One的一方指向Many的一方,並且,這個屬性應該等於Many的一方中含有One類的屬性的屬性名,否則會出錯啦
cascade:CascadeType[]類型。該屬性定義類和類之間的級聯關系。
定義的級聯關系將被容器視為對當前類對象及其關聯類對象采取相同的操作,而且這種關系是遞歸調用的。
舉個例子:Order 和OrderItem有級聯關系,那么刪除QingAoCenterInfo時將同時刪除它所對應的QingAoPlaceInfo對象。而如果QingAoPlaceInfo還和其他的對象之間有級聯關系,那么這樣的操作會一直遞歸執行下去。
cascade的值只能從CascadeType.PERSIST(級聯新建)、CascadeType.REMOVE(級聯刪除)、CascadeType.REFRESH(級聯刷新)、CascadeType.MERGE(級聯更新)中選擇一個或多個。還有一個選擇是使用CascadeType.ALL,表示選擇全部四項。

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
package com.yuqiaotech.nttelcom.model;

import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
* 青奧重點場所信息表。
*
*/
@Entity(name="QING_AO_CENTER_INFO")
@Table(name="QING_AO_CENTER_INFO")
public class QingAoCenterInfo {
private Long id;
private String centerName; //重點場所名稱
private Long alarmNum; //告警數
private String note; //備注
private String iconName; //圖標名稱
private String cityName; //所在城市
private String type; //重點場所、活動保障
private Date createTime;
private List<QingAoPlaceInfo> qingAoPlaceInfo; //場所擁有的場館
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @searchItem
* displayType="text"
*
* 重點場所名稱
* @return
*/
public String getCenterName() {
return centerName;
}
public void setCenterName(String centerName) {
this.centerName = centerName;
}
/**
* 告警數
* @return
*/
public Long getAlarmNum() {
return alarmNum;
}
public void setAlarmNum(Long alarmNum) {
this.alarmNum = alarmNum;
}
/**
* 備注
* @return
*/
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
/**
* 圖標名稱
* @return
*/
public String getIconName() {
return iconName;
}
public void setIconName(String iconName) {
this.iconName = iconName;
}

public String getCityName() {
return cityName;
}

public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@OneToMany(mappedBy="qingAoCenterInfo",cascade= CascadeType.ALL)
public List<QingAoPlaceInfo> getQingAoPlaceInfo() {
return qingAoPlaceInfo;
}
public void setQingAoPlaceInfo(List<QingAoPlaceInfo> qingAoPlaceInfo) {
this.qingAoPlaceInfo = qingAoPlaceInfo;
}
}


many端:QingAoPlaceInfo,持有QingAoCenterInfo的引用
通過@ManyToOne(fetch=FetchType.LAZY ) @JoinColumn(name="f_center_id")設置關聯關系
@ManyToOne指明QingAoPlaceInfo和QingAoCenterInfo之間為多對一關系,多個QingAoPlaceInfo實例關聯的都是同一個QingAoCenterInfo對象
fetch和lazy是用來定義級聯查詢的方式:
fetch:官方文檔里對fetch有如下描述,Hibernate3 定義了如下幾種抓取策略:
連接抓取(Join fetching):Hibernate 通過在 SELECT 語句使用 OUTER JOIN(外連接)來獲得對象的關聯實例或者關聯集合。
查詢抓取(Select fetching):另外發送一條 SELECT 語句抓取當前對象的關聯實體或集合。除非你顯式的指定 lazy="false" 禁止 延遲抓取(lazy fetching),否則只有當你真正訪問關聯關系的時候,才會執行第二條 select 語句。
子查詢抓取(Subselect fetching):另外發送一條 SELECT 語句抓取在前面查詢到(或者抓取到)的所有實體對象的關聯集合。除非你顯式的指定 lazy="false" 禁止延遲抓取(lazy fetching),否則只有當你真正訪問關聯關系的時候,才會執行第二條 select 語句。
批量抓取(Batch fetching):對查詢抓取的優化方案,通過指定一個主鍵或外鍵列表,Hibernate 使用單條 SELECT 語句獲取一批對象實例或集合。

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
package com.yuqiaotech.nttelcom.model;

import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
* 場館信息。
*
*/
@Entity(name="QING_AO_PLACE_INFO")
@Table(name="QING_AO_PLACE_INFO")
public class QingAoPlaceInfo {
private Long id;
private QingAoCenterInfo qingAoCenterInfo;// 重點場所id
private String placeName;// 場館名稱
private String note;// 備注
private String openStat;// 開通狀態
private Long displayOrder;
private String cityName;
private Date createTime;
private List<QingAoPlaceCdmaSector> qingAoPlaceCdmaSector;//擁有的cdma
private List<QingAoPlaceLteSector> qingAoPlaceLteSector;//擁有的Lte
private List<QingAoAp> qingAoAp; //擁有的Ap


@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

@ManyToOne(fetch=FetchType.LAZY )
@JoinColumn(name="f_center_id")
public QingAoCenterInfo getQingAoCenterInfo() {
return qingAoCenterInfo;
}

public void setQingAoCenterInfo(QingAoCenterInfo qingAoCenterInfo) {
this.qingAoCenterInfo = qingAoCenterInfo;
}
/**
* @searchItem
* displayType="text"
* 場所名稱
* @return
*/
public String getPlaceName() {
return placeName;
}
public void setPlaceName(String placeName) {
this.placeName = placeName;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

public String getOpenStat() {
return openStat;
}

public void setOpenStat(String openStat) {
this.openStat = openStat;
}

public Long getDisplayOrder() {
return displayOrder;
}

public void setDisplayOrder(Long displayOrder) {
this.displayOrder = displayOrder;
}

public String getCityName() {
return cityName;
}

public void setCityName(String cityName) {
this.cityName = cityName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@OneToMany(mappedBy="qingAoPlaceInfo",cascade= CascadeType.ALL)
public List<QingAoPlaceCdmaSector> getQingAoPlaceCdmaSector() {
return qingAoPlaceCdmaSector;
}

public void setQingAoPlaceCdmaSector(
List<QingAoPlaceCdmaSector> qingAoPlaceCdmaSector) {
this.qingAoPlaceCdmaSector = qingAoPlaceCdmaSector;
}
@OneToMany(mappedBy="qingAoPlaceInfo",cascade= CascadeType.ALL)
public List<QingAoPlaceLteSector> getQingAoPlaceLteSector() {
return qingAoPlaceLteSector;
}

public void setQingAoPlaceLteSector(
List<QingAoPlaceLteSector> qingAoPlaceLteSector) {
this.qingAoPlaceLteSector = qingAoPlaceLteSector;
}
@OneToMany(mappedBy="qingAoPlaceInfo",cascade= CascadeType.ALL)
public List<QingAoAp> getQingAoAp() {
return qingAoAp;
}

public void setQingAoAp(List<QingAoAp> qingAoAp) {
this.qingAoAp = qingAoAp;
}
}

3、Hibernate4 注解版關系案例

一對多和多對一

公司用的maven 所以我也是建的maven工程,導入hibernate4的jar包
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.6.Final</version>
</dependency>

但是oracle的驅動包,好像要自己手動加。不知道有沒有用maven直接從網上加的方法。
hibernate.cfg.xml 文件
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>

<!-- 數據庫信息 -->
<property name="dialect">
org.hibernate.dialect.Oracle10gDialect
</property>
<property name="connection.url">jdbc:oracle:thin:@192.168.15.102:1521:ora11g</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.username">iris_ecnu_dev</property>
<property name="connection.password">iris_ecnu_dev</property>

<!-- 其他配置 -->
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<property name="format_sql">true</property>

<!-- 導入映射配置 -->
<mapping class="cn.lzg.Order" />
<mapping class="cn.lzg.Person" />
</session-factory>
</hibernate-configuration>

Order.java 文件
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
package cn.lzg;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "order_lzg")
public class Order {

@Id
@SequenceGenerator(name = "order_lzg", sequenceName = "o_seq", allocationSize = 1)
@GeneratedValue(generator = "order_lzg", strategy = GenerationType.SEQUENCE)
private Long order_id;

@Column(name = "submit_time")
private Date submit_time;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "p_id")
// order_lzg表 里面 放person_lzg ID的列
private Person person_lzg;

public Order() {
}

public Long getOrder_id() {
return order_id;
}

public void setOrder_id(Long order_id) {
this.order_id = order_id;
}

public Date getSubmit_time() {
return submit_time;
}

public void setSubmit_time(Date submit_time) {
this.submit_time = submit_time;
}

public Person getPerson_lzg() {
return person_lzg;
}

public void setPerson_lzg(Person person_lzg) {
this.person_lzg = person_lzg;
}

}

Person.java 文件
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
package cn.lzg;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "person_lzg")
public class Person {

@Id
@SequenceGenerator(name = "person_lzg", sequenceName = "p_seq", allocationSize = 1)
@GeneratedValue(generator = "person_lzg", strategy = GenerationType.SEQUENCE)
private Long p_id;

@Column(name = "name")
private String name;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "person_lzg")
// mappedBy的值,是Order對象里面存Person對象的屬性的值
private Set<Order> orderSet = new HashSet<Order>();

public Long getp_id() {
return p_id;
}

public void setp_id(Long p_id) {
this.p_id = p_id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set<Order> getOrderSet() {
return orderSet;
}

public void setOrderSet(Set<Order> orderSet) {
this.orderSet = orderSet;
}

}

多對多

其實它的和 一對多 差不多,但是按照網上寫法出現了一個問題,使得 雙向的關系變成了單向的。
Person類
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
package cn.lzg;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "person_lzg")
public class Person {

@Id
@SequenceGenerator(name = "person_lzg", sequenceName = "p_seq", allocationSize = 1)
@GeneratedValue(generator = "person_lzg", strategy = GenerationType.SEQUENCE)
private Long p_id;

@Column(name = "name")
private String name;

@ManyToMany(targetEntity = cn.lzg.Book.class, fetch = FetchType.LAZY)
@JoinTable(name = "lzgp_lzgb", joinColumns = { @JoinColumn(name = "p_id") }, inverseJoinColumns = { @JoinColumn(name = "b_id") })
// name中間表的名字,第一個自己的主鍵,第二個關聯的主鍵
private List<Book> books = new ArrayList<Book>();

public Long getP_id() {
return p_id;
}

public void setP_id(Long p_id) {
this.p_id = p_id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<Book> getBooks() {
return books;
}

public void setBooks(List<Book> books) {
this.books = books;
}

}
Book類
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
package cn.lzg;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "book_lzg")
public class Book {
@Id
@SequenceGenerator(name = "book_lzg", sequenceName = "b_seq", allocationSize = 1)
@GeneratedValue(generator = "book_lzg", strategy = GenerationType.SEQUENCE)
private Long b_id;

@Column(name = "name")
private String name;

@ManyToMany(targetEntity = cn.lzg.Person.class, fetch = FetchType.LAZY)
<span style="color:#FF0000;">// 如果在上面使用mappedBy后,就成單向的了.也就是mappedBy出現的位置所在的類,這個類是被維護端,它只能被別人級聯,不能去保存別人.
// 這個問題搞了好久才發現,開始一直是單向的.</span>
@JoinTable(name = "lzgp_lzgb", joinColumns = { @JoinColumn(name = "b_id") }, inverseJoinColumns = { @JoinColumn(name = "p_id") })
private List<Person> persons = new ArrayList<Person>();

public Long getB_id() {
return b_id;
}

public void setB_id(Long b_id) {
this.b_id = b_id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<Person> getPersons() {
return persons;
}

public void setPersons(List<Person> persons) {
this.persons = persons;
}

}
注意
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
<span style="color:#FF0000;">如果在上面ManyToMany注解中使用mappedBy,就成單向的了.因為mappedBy出現的位置所在的類,這個類是被維護端,它只能被別人級聯,不能去保存別人

<span style="color:#330033;">測試類
</span></span><pre name="code" class="java">package cn.lzg;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.Test;

public class TestHibernate {
private static Configuration configuration = null;
private static SessionFactory sessionFactory = null;
private static ServiceRegistry serviceRegistry = null;
private static Session session = null;

static {
/**
* hibernate 4 貌失要這樣獲得sessionFactory 以前的configuration.buildSessionFactory();方法 過時了
*/
configuration = new Configuration().configure();

serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();

sessionFactory = configuration.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
}



@Test
// 測試manytomany
public void testM2M() {
Person p1 = new Person();
p1.setName("張三");
Person p2 = new Person();
p2.setName("李四");
Person p3 = new Person();
p3.setName("王五");
List<Person> persons = new ArrayList<Person>();
persons.add(p1);
persons.add(p2);
persons.add(p3);

Book b1 = new Book();
b1.setName("書本1");
Book b2 = new Book();
b2.setName("書本2");
Book b3 = new Book();
b3.setName("書本3");
List<Book> books = new ArrayList<Book>();
books.add(b1);
books.add(b2);
books.add(b3);

p1.setBooks(books);
b3.setPersons(persons);

Transaction tx = session.beginTransaction();
session.save(p1);
session.save(p2);
session.save(p3);
session.save(b1);
session.save(b2);
session.save(b3);
tx.commit();
session.close();
}
}


結果生成了中間表
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
lzgp_lzgb 里面的關系p1 有三本書, p1,p2,p3都有b3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM