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

原创 2016年04月10日 18:13:45

hibernate一对一关联映射有两种方式,一种是基于外键方式(常用),一种是基于主键方式

一、首先我们来看基于外键一对一关联映射:

 

1.数据表关联映射图


基于外键的一对一关联映射,维护端(有外键方)可以维护双方关联,对双方进行删除操作,而被维护端(无外键方)则不可以

2.Customer实体类,维护端(有外键方)

@Entity
@Table(name = "T_FOREIGN_CUSTOMER")
public class Customer {
	private int id;
	private String name;
	private Referee referee;

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

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

	public String getName() {
		return name;
	}

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

	/**
	 * 默认外键名referee_id
	 * @OneToOne public Referee getReferee() { return referee; }
	 * @return
	 */

	/**
	 * /使用新的外键名:referee1_id
	 * @OneToOne
	 * @JoinColumn(name="referee1_id") public Referee getReferee() { return
	 * @return
	 */
	@OneToOne
	@JoinColumn(name = "referee_id")
	// 维护端
	public Referee getReferee() {
		return referee;
	}

	/**
	 * 从上面的代码可以看出,getReferee方法使用了@OneToOne进设置
	 * 在装载Customer对象的同时,Referee对象会被同时装载,而默认的外键字段就是Customer类中的referee属性名+"_"+id
	 * 也就是referee_id
	 * @param referee
	 */
	public void setReferee(Referee referee) {
		this.referee = referee;
	}

}
 3.Referee实体类:被维护端(无外键方)
@Entity
@Table(name="T_FOREIGN_REFEREE")
public class Referee {
	private int id;
	private String name;
	private Customer customer;
	
	@Id
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "T_FOREIGN_REFEREE_GEN")
	@TableGenerator(name = "T_FOREIGN_REFEREE_GEN", table = "TB_GENERATOR", pkColumnName = "GEN_NAME", valueColumnName = "GEN_VALUE", pkColumnValue = "T_FOREIGN_REFEREE_GEN", allocationSize = 1)
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	//mappedBy表示被维护端
	@OneToOne(mappedBy="referee")
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
	
}
 4.CustomerService服务类:
@Service("customerService")
@Transactional
public class CustomerService {
	@Resource
	private SessionFactory sessionFactory;

	public void saveForgin() {

		Customer customer = new Customer();
		customer.setName("微软");

		Referee referee = new Referee();
		referee.setName("赵军");
		customer.setReferee(referee);
		referee.setCustomer(customer);
		// 先保存无外键方
		sessionFactory.getCurrentSession().persist(referee);
		sessionFactory.getCurrentSession().persist(customer);

	}

	public Customer getCustomer(int id) {
		return (Customer) sessionFactory.getCurrentSession().get(
				Customer.class, id);
	}
	

	public Referee getReferee(int id) {
		return (Referee) sessionFactory.getCurrentSession().get(Referee.class,
				id);
	}
	
		
	/**
	 * 维护端(有外键方)可以维护关系 移除关联关系
	 */
	public void RemoveRelationForeign() {
		Customer customer = (Customer) sessionFactory.getCurrentSession().get(
				Customer.class, 1);
		customer.setReferee(null);
		sessionFactory.getCurrentSession().persist(customer);
	}

	/**
	 * 被维护端(无外键方),无法维护关系 ,不可以维护关联关系,所以删除Referee时,如果有关联的Customer,就会抛异常 导致双方都删除不成功
	 */
	public void RemoveRelationNoForeign() {
		sessionFactory.getCurrentSession().delete(
				sessionFactory.getCurrentSession().get(Referee.class, 1));
	}
	/**
	 * 维护端(外键方)可以维护关系,
	 * 会先移除关联关系
	 * 删除有外键方,
	 */
	public void RemoveRelationForeignOne()  {
		sessionFactory.getCurrentSession().delete(
				sessionFactory.getCurrentSession().get(Customer.class, 1));
	}
	public void deleteFromNoforeign(){
		////先删除有外键方
		sessionFactory.getCurrentSession().delete(
				sessionFactory.getCurrentSession().get(Referee.class, 1));
	}
	public void deleteFromForeign(){
		////先删除有外键方
		sessionFactory.getCurrentSession().delete(
				sessionFactory.getCurrentSession().get(Customer.class, 1));
	}
	public void DeleteForeignTow()   {
		////先删除有外键方
		sessionFactory.getCurrentSession().delete(
				sessionFactory.getCurrentSession().get(Customer.class, 1));
		//再删除无外键方
		sessionFactory.getCurrentSession().delete(
				sessionFactory.getCurrentSession().get(Referee.class, 1));
	}
	@SuppressWarnings("unchecked")
	public List<Customer> getCustomers(){
		return sessionFactory.getCurrentSession().createQuery("from Customer").list();
	}
	
	@SuppressWarnings("unchecked")
	public List<Referee> getReferees(){
		return sessionFactory.getCurrentSession().createQuery("from Referee").list();
	}
	

}
 5.测试类:

public class CustomerServiceTest {
	private static CustomerService customerService;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		try {
			ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
					"beans.xml");
			customerService = (CustomerService) applicationContext
					.getBean("customerService");
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}

	// 测试保存
	@Test
	public void testSaveForgin() {
		customerService.saveForgin();
	}

	// 测试获取关联对象的属性值
	// 两个sql,有外键方
	@Test
	public void testGetCustomer() {
		Customer customer = customerService.getCustomer(1);
		System.out.println(customer.getReferee().getName());
	}

	// 测试获取关联对象的属性值
	// 1条sql,无外键方
	@Test
	public void testGetReferee() {
		Referee referee = customerService.getReferee(1);
		System.out.println(referee.getCustomer().getName());
	}

	// 2条sql
	@Test
	public void testGetReferees() {
		for (Referee r : customerService.getReferees()) {
			System.out.println(r.getName());
		}
	}

	// 3条sql
	@Test
	public void testGetCustomers() {
		for (Customer c : customerService.getCustomers()) {
			System.out.println(c.getName());
		}
	}

	// 测试移除关联有关系
	// 维护端(外键方)可以维护关系 移除关联关系
	@Test
	public void testRemoveRelationForeign() {
		customerService.RemoveRelationForeign();
	}

	// 测试移除关联有关系
	// 被维护端(无外键方),无法维护关系 ,不可以维护关联关系,所以删除Referee时,
	// 如果有关联的Customer,就会抛异常 导致双方都删除不成功
	@Test
	public void testRemoveRelationNoForeign() {
		customerService.RemoveRelationNoForeign();

	}

	// 删除被维护端(无外键方),不能删除
	@Test
	public void testdeleteFromNoforeign() {
		customerService.deleteFromNoforeign();
	}

	// 删除维护端(有外键方),可以删除
	@Test
	public void testDeleeteForeignOne() {
		customerService.deleteFromForeign();
	}

	// 两个再时删除,先删除有维护端(有外键方),再删除被维护端(外键方)
	@Test
	public void testDeleteForeignTow() {
		customerService.DeleteForeignTow();
	}
}

二、基于主键一对一关联映射

       基于主键一对一关联,双方都不可以维护关联(不如基于外键的一对一关联),有外键方可以进行删除(双方都删除),无外键方不能进行删除

     

1.数据表关联映射图



 2.CustomerPrimary实体类,关联维护端(有外键方)

@Entity
@Table(name = "T_PRIMARY_CUSTOMER")
public class CustomerPrimary {
	private int id;
	private String name;
	private RefereePrimary referee;

	@Id
	// 标注表示这个id属性是外键,并且依赖于customer属性相对应的实体bean的id属性值(主键值)
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "T_PRIMARY_CUSTOMER_GEN")
	@TableGenerator(name = "T_PRIMARY_CUSTOMER_GEN", table = "TB_GENERATOR", pkColumnName = "GEN_NAME", valueColumnName = "GEN_VALUE", pkColumnValue = "T_PRIMARY_CUSTOMER_GEN", allocationSize = 1)
	public int getId() {
		return id;
	}

	/**
	 * 注意: 由于t_referee表的id自增类型已经去掉而且该类依赖于t_customers表的id字段值
	 * ,因此就不能直接持久化referee对象了,而是持久化customer对象的同时,ejb3容器会自动将referee持久化的
	 * 
	 * @param id
	 */
	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	// 共享主键
	@OneToOne(cascade = CascadeType.ALL)
	@PrimaryKeyJoinColumn
	public RefereePrimary getReferee() {
		return referee;
	}

	public void setReferee(RefereePrimary referee) {
		this.referee = referee;
	}

}

3. RefereePrimary实体类:关系被维护端(无外键方)

@Entity
@Table(name="T_PRIMARY_REFEREE")
public class RefereePrimary {
	private int id;
	private String name;
	private CustomerPrimary customer;
	@OneToOne
	@PrimaryKeyJoinColumn
	public CustomerPrimary getCustomer() {
		return customer;
	}
	public void setCustomer(CustomerPrimary customer) {
		this.customer = customer;
	}
	//采用基于主键的一对一映射时,要把主键生成策略改为foreign
	//属性对应customer
	@Id
	@GeneratedValue(generator="pkGenerator")
	@GenericGenerator(name="pkGenerator",strategy="foreign",
	parameters=@Parameter(name="property",value="customer"))
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

 4.CustomerPrimaryService服务类

@Service("customerPrimaryService")
@Transactional
public class CustomerPrimaryService  {
	@Resource
	private SessionFactory sessionFactory;
	//测试保存
	public void savePrimary() {
		CustomerPrimary customer = new CustomerPrimary();
		customer.setName("微软");

		RefereePrimary referee = new RefereePrimary();
		referee.setName("赵军");
		// 关联起来
		// 使用基于主键的一对一时:也是只有有外键方可以保存关联关系
		customer.setReferee(referee);
		referee.setCustomer(customer);
		// 先保存无外键方,先保存主键方
		sessionFactory.getCurrentSession().persist(customer);
		// 再保存有外键方,因为有外键方要引用无外键方的主键值
		sessionFactory.getCurrentSession().persist(referee);

	}
	//测试根据id获取
	public CustomerPrimary getCustomerPrimary(int id) {
		return (CustomerPrimary) sessionFactory.getCurrentSession().get(
				CustomerPrimary.class, 1);
	}
	//测试根据id获取
	public RefereePrimary getRefereePrimary(int id) {
		return (RefereePrimary) sessionFactory.getCurrentSession().get(
				RefereePrimary.class, 1);
	}

	// 移除关联关系
	// 使用基于主键的一对一时,双方都不可以移除关联关系
	public void RemoveRelationPrimary() {
		CustomerPrimary customer = (CustomerPrimary) sessionFactory
				.getCurrentSession().get(CustomerPrimary.class, 1);
		customer.setReferee(null);
		sessionFactory.getCurrentSession().persist(customer);
	}

	// 移除关联关系
	// 使用基于主键的一对一时,双方都不可以移除关联关系
	public void RemoveRelationNoPrimary() {
		RefereePrimary referee = (RefereePrimary) sessionFactory
				.getCurrentSession().get(RefereePrimary.class, 1);
		referee.setCustomer(null);
		sessionFactory.getCurrentSession().persist(referee);
	}

	// 因为RefereePrimary是无外键言,不可以维护关联关系,所以删除RefereePrimary时,如果有关联的Customer,就会抛异常
	// 因为CustomerPrimary的id有引用RefereePrimary的id
	public void DeleteNoForeign() {
		sessionFactory.getCurrentSession()
				.delete(sessionFactory.getCurrentSession().get(
						RefereePrimary.class, 1));
	}
	//删除就同时删除CustomerPrimary与RefereePrimary记录
	public void DeleteForeign() {
		sessionFactory.getCurrentSession().delete(
				sessionFactory.getCurrentSession()
						.get(CustomerPrimary.class, 1));
	}
	//测试删除
	public void DeleteAll() {
		// 先删除有外键方
		sessionFactory.getCurrentSession().delete(
				sessionFactory.getCurrentSession()
						.get(CustomerPrimary.class, 2));

	}
	//测试获取列表信息
	@SuppressWarnings("unchecked")
	public List<CustomerPrimary> getCustomerPrimarys(){
		return sessionFactory.getCurrentSession().createQuery("from CustomerPrimary").list();
	}
	//测试获取列表信息
	@SuppressWarnings("unchecked")
	public List<RefereePrimary> getRefereePrimarys(){
		return sessionFactory.getCurrentSession().createQuery("from RefereePrimary").list();
	}
	
	//测试根据id获取
	public CustomerPrimary loadCustomerPrimary(int id) {
		return (CustomerPrimary) sessionFactory.getCurrentSession().get(
				CustomerPrimary.class, 1);
	}
	//测试根据id获取
	public RefereePrimary loadRefereePrimary(int id) {
		return (RefereePrimary) sessionFactory.getCurrentSession().get(
				RefereePrimary.class, 1);
	}
}
 5.测试类

public class CustomerPrimaryServiceTest {
	private static CustomerPrimaryService customerPrimaryService;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		try {
			ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
					"beans.xml");
			customerPrimaryService = (CustomerPrimaryService) applicationContext
					.getBean("customerPrimaryService");
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}
	//测试保存
	@Test
	public void testSavePrimary() {
		customerPrimaryService.savePrimary();
	}
	//测试获取关联获取值
	//一条sql
	@Test 
	public void testGetPrimaryCustomer(){
		CustomerPrimary customer=customerPrimaryService.getCustomerPrimary(1);
		System.out.println(customer.getReferee().getName());
	}
	//测试获取关联获取值
	//一条sql
	@Test 
	public void testGetPrimaryReferee(){
		RefereePrimary referee=customerPrimaryService.getRefereePrimary(1);
		System.out.println(referee.getCustomer().getName());
	}
	//测试移除关系关系
	@Test
	public void testRemoveRelationPrimary(){
		customerPrimaryService.RemoveRelationPrimary();
	}
	//测试移除关系关系
	@Test
	public void testRemoveRelationNoPrimary(){
		customerPrimaryService.RemoveRelationNoPrimary();
	}
	//无外键方,不可以删除
	@Test
	public void testDeleteNoForeign(){
		customerPrimaryService.DeleteNoForeign();
	}
	// 有外键方 可以删除,删除是删除两个表的信息
	
	@Test
	public void testDeleteForeign(){
		customerPrimaryService.DeleteForeign();
	}
	//n+1条
	//测试获取列表信息
	@Test
	public void testGetCustomerPrimarys(){
		for(CustomerPrimary c:customerPrimaryService.getCustomerPrimarys()){
			System.out.println(c.getName());
		}
	}
	//n+1条
	//测试获取列表信息
	@Test
	public void testGetPrimaryReferees(){
		for(RefereePrimary r:customerPrimaryService.getRefereePrimarys()){
			System.out.println(r.getName());
		}
	}
}
说明:本人于ITEYE创建于2013年,现转移到CSDN


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

hibernate关联关系注解(一对多、多对一、一对一)

一对多、多对一、一对一的注解实现 casecade={CasecadeType.REFRESH}的含义是只是查询级联,它还有其他3个类型: CascadeType.MERGE级联更新 CascadeT...

Hibernate注解版用一对一实例

1 写三个数据库表,两个基础表,一个关联外键表,个人认为可以用两个表代替,用三个表的原因个人理解为是因为互为外键,建立的时候没有基础表,所以澡了第三个表,可以,先建立一个,然后更改表约束,应该也可以【...

Hibernate4注解详解之一对一对象映射

这里我通过不断测试,给hibernate4的注解功能到mysql数据库的映射,做了一个比较全的介绍。

Hibernate的关联关系注解映射(一对一、一对多、多对一、多对多、自连接)

1. 一对多关系: 在一的一方添加注解@OneToMany(targetEntity=Goods.class,cascade=CascadeType.ALL),指定cascade为all,即交由多的一...

【Hibernate】二、Hibernate映射详解(一对一单向关联)

Hibernate的目的就是让开发人员觉得好像是将JAVA对象存储到了数据库里一样。但是,我们知道数据库中只有表,如何将java对象经过Hibernate存储到数据库中,又如何将数据库中存储的数据通过...

Hibernate关系映射(一)一对一单向外键关联@OneToOne Annotation方式

首先构造一个场景,实体:国家(country),它具有以下属性,Id,名称,使用货币,首都。实体:首都(capital),它具有以下属性,Id,名称。一个国家有且仅有一个首都,一个首都只能属于一个国家...

Hibernate关联关系配置(一对多、一对一和多对多)

第一种关联关系:一对多(多对一) "一对多"是最普遍的映射关系,简单来讲就如消费者与订单的关系。 一对多:从消费者角的度来说一个消费者可以有多个订单,即为一对多。 多对一:从订单的角...

Hibernate注解实现一对一关联

本文使用Hibernate Annotation实现一对一关联。
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)