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