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

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)
)

 一对多:数据表关系映射图

 
Hibernate一对多关联映射(注解)_第1张图片
 

你可能感兴趣的:(Hibernate,一对多,OneyToMany)