您的位置:首页 > 其它

Hibernate一对多关联映射(注解)

2016-04-10 18:35 441 查看
Hibernate一对多关联映射,维护端(一方,无外键方)可以进行关联移除,级联删除,级联保存,级联更新,级联刷新。被维护端(多方,外键方),不可以进行关联移除,级联操作,只能级联刷新。

Spring中bean.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!-- 基于注解方式 http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd"> 
<context:annotation-config />
<context:component-scan base-package="com.entityBean"></context:component-scan>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" />
<property name="username" value="hibernate" />
<property name="password" value="hibernate" />
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="1" />
<!-- 连接池的最大值 -->
<property name="maxActive" value="500" />
<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="2" />
<!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property name="minIdle" value="1" />
</bean>
<!-- org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
基于注解的sessionFactroy -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
name="sessionFactory">
<property name="dataSource" ref="dataSource" />

<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.OracleDialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=false
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
</value>
</property>
<!-- annotatedClasses -->
<property name="annotatedClasses">
<list>
<value>com.entityBean.one2many.bean.Order</value>
<value>com.entityBean.one2many.bean.OrderItem</value>

</list>
</property>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven transaction-manager="txManager" />

</beans>
Order(维护端,无外键方,一方)

@Entity
@Table(name="T_ORDER")
@SuppressWarnings("serial")
public class Order implements Serializable {
private Integer id;
private String bak;
private Set<OrderItem> orderItems = new HashSet<OrderItem>();
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "T_ORDER_GEN")
@TableGenerator(name = "T_ORDER_GEN", table = "TB_GENERATOR", pkColumnName = "GEN_NAME", valueColumnName = "GEN_VALUE", pkColumnValue = "T_ORDER_GEN", allocationSize = 1)
public Integer getId() {
return id;
}

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

public String getBak() {
return bak;
}

public void setBak(String bak) {
this.bak = bak;
}
/**一对多那方:设置懒加载*/
@OneToMany(mappedBy="order",cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@OrderBy(value = "id ASC")/**指明加载OrderItem 时按id 的升序排序*/
public Set<OrderItem> getOrderItems() {
return orderItems;
}

public void setOrderItems(Set<OrderItem> orderItems) {
this.orderItems = orderItems;
}

@Override
public String toString() {
return "Order [id=" + id + ", bak=" + bak + ", orderItems="
+ orderItems + "]";
}
}
OrderItem(被维护端,有外键方,多方)

@Entity
@Table(name="T_ORDERITEM")
@SuppressWarnings("serial")
public class OrderItem implements Serializable {
private Integer id;
//不能定义关联的列
//private Integer order_id;
private String bak;
private Order order;

@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "T_ORDERITEM_GEN")
@TableGenerator(name = "T_ORDERITEM_GEN", table = "TB_GENERATOR", pkColumnName = "GEN_NAME", valueColumnName = "GEN_VALUE", pkColumnValue = "T_ORDERITEM_GEN", allocationSize = 1)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}

public String getBak() {
return bak;
}
public void setBak(String bak) {
this.bak = bak;
}
/**级联刷新*/
/**optional表示该对象可有可无,它的值为true表示该外键可以为null,它的值为false表示该外键为not null*/
@ManyToOne(cascade=CascadeType.REFRESH,optional=false,fetch = FetchType.LAZY)
/**指定外键列(这也表示为所在对象为“关系被维护端”)*/
@JoinColumn(name = "order_id")
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
@Override
public String toString() {
return "OrderItem [id=" + id + ", bak=" + bak + "]";
}
}
OrderService

@Service("orderService")
@Transactional
public class OrderService {
@Resource
private SessionFactory sessionFactory;

/** 从一方保存 (1:一方与多方关系起来2.保存一方)*/
public void saveFromOne() {
Order order = new Order();
order.setBak("订单");
OrderItem orderItem1 = new OrderItem();
orderItem1.setBak("明细1");
orderItem1.setOrder(order);
OrderItem orderItem2 = new OrderItem();
orderItem2.setBak("明细2");
orderItem2.setOrder(order);
Set<OrderItem> orderItems = new HashSet<OrderItem>();
orderItems.add(orderItem1);
orderItems.add(orderItem2);

// 关联起来
order.setOrderItems(orderItems);

// 保存
sessionFactory.getCurrentSession().persist(order);

}

public void saveFromOne2() {
Order order = new Order();
order.setBak("订单");
OrderItem orderItem1 = new OrderItem();
orderItem1.setBak("明细1");
// 多方关联一方
orderItem1.setOrder(order);
OrderItem orderItem2 = new OrderItem();
orderItem2.setBak("明细2");
// 多方关联一方
orderItem2.setOrder(order);
// 一方关联多方
order.getOrderItems().add(orderItem1);
order.getOrderItems().add(orderItem2);

sessionFactory.getCurrentSession().persist(order);
}

/** 多方关联保存,先保存依赖的一方,这样会省略update sql提高效率*/
public void saveFromMany() {
Order order = new Order();
order.setBak("订单");
OrderItem orderItem1 = new OrderItem();
orderItem1.setBak("明细1");
orderItem1.setOrder(order);
OrderItem orderItem2 = new OrderItem();
orderItem2.setBak("明细2");
orderItem2.setOrder(order);

// 1.先保存无外键方
sessionFactory.getCurrentSession().persist(order);

// 2.再保存有外键方
sessionFactory.getCurrentSession().persist(orderItem1);
sessionFactory.getCurrentSession().persist(orderItem2);

}

// 存在n+1问题
public Order getOrderByID(Integer orderid) {
Order order = (Order) sessionFactory.getCurrentSession().get(
Order.class, orderid);
// !!!!!因为是延迟加载,通过执行size()这种方式获取订单下的所有订单项
order.getOrderItems().size();
return order;
}

// inner join 连接解决n+1问题 根据订单id查询订单和明细
public List getOrderByIDNoN_1(Integer orderid) {
List orders = sessionFactory
.getCurrentSession()
.createQuery(
"select DISTINCT o from Order o inner join fetch o.orderItems where o.id='"
+ orderid + "' order by o.id").list();
return orders;
}

// 查询所有订单和明细
public List getAllOrder() {
List result = sessionFactory
.getCurrentSession()
.createQuery(
"select DISTINCT o from Order o inner join fetch o.orderItems order by o.id")
.list();
return result;
}
/**
* 被维护端(多方,外键方)
*被维护端,无法移除关系,移除关系会报错 */
public void removeRelationFromBeMaintained (Integer orderItemId) {
OrderItem orderItem = (OrderItem) sessionFactory.getCurrentSession()
.get(OrderItem.class, orderItemId);
orderItem.setOrder(null);
sessionFactory.getCurrentSession().persist(orderItem);
}

/**
*维护端(一方,无外键方)
*维护端:可以移除关系
*/
public void removeRelationFromMaintained(Integer orderid) {
sessionFactory.getCurrentSession().delete(
sessionFactory.getCurrentSession().get(Order.class, orderid));
}

/**从被维护端删除,不能删除维护端*/
public void deleteFromNoMaintained(Integer orderItemId) {
sessionFactory.getCurrentSession().delete(
sessionFactory.getCurrentSession().get(OrderItem.class, orderItemId));
}
/**从维护端删除,级联删除*/
public void deleteFromMaintained(Integer id) {
sessionFactory.getCurrentSession().delete(
sessionFactory.getCurrentSession().get(Order.class, id));
}
/**删除:双边删除*/
public void deleteFromBothSide(Integer orderId, Integer orderitemId) {
//1.先删除有外键方(被维护端)
sessionFactory.getCurrentSession().delete(
sessionFactory.getCurrentSession()
.get(OrderItem.class, orderitemId));
//2.再删除无外键方(维护端)
sessionFactory.getCurrentSession().delete(
sessionFactory.getCurrentSession()
.get(Order.class, orderId));
}
}
测试类:

public class OrderServiceTest {
private static OrderService orderService;

@BeforeClass
public static void setUpBeforeClass() throws Exception {
try {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"beans.xml");
orderService = (OrderService) applicationContext
.getBean("orderService");
} catch (RuntimeException e) {
e.printStackTrace();
}
}
@Test
public void saveFromOne(){
orderService.saveFromOne();
}
@Test
public void saveFromOne2() {
orderService.saveFromOne2();
}
@Test
public void saveFromMany() {
orderService.saveFromMany();
}
@Test
public void  getOrderByID() {
Order order=orderService.getOrderByID(1);
System.out.println(order);
}
@Test
public void getOrderByIDNoN_1() {
List orders = orderService.getOrderByIDNoN_1(1);
for (Order o : (List<Order>) orders) {
System.out.println(o.getBak());
for (OrderItem r : (Set<OrderItem>) o.getOrderItems())
System.out.println(r.getBak());
}

}
@Test
public void getOrderAll() {
List orders = orderService.getAllOrder();
System.out.println(orders.size());
for (Order o : (List<Order>) orders) {
System.out.println(o.getBak());
for (OrderItem r : (Set<OrderItem>) o.getOrderItems())
System.out.println(r.getBak());
}
}
@Test
public void removeRelationFromBeMaintained () {
orderService.removeRelationFromBeMaintained(1);
}

@Test
public void removeRelationFromMaintained(Integer orderid) {
orderService.removeRelationFromMaintained(1);
}

@Test
public void deleteFromMaintained(Integer orderItemId) {
orderService.deleteFromMaintained(1);
}
@Test
public void deleteFromNoMaintained(Integer orderItemId) {
orderService.deleteFromNoMaintained(1);
}
@Test
public void deleteFromBothSide() {
orderService.deleteFromBothSide(1, 2);

}
}
表主键自增对照表SQL

create table TB_GENERATOR
(
GEN_NAME  VARCHAR2(255),
GEN_VALUE NUMBER(10)
)
一对多:数据表关系映图



说明:本人于ITEYE创建于2013年,现转移到CSDN
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: