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

来源:互联网 发布:新域名一般几天收录 编辑:程序博客网 时间:2024/05/11 05:10

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")@Transactionalpublic class CustomerService {@Resourceprivate 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;@BeforeClasspublic static void setUpBeforeClass() throws Exception {try {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");customerService = (CustomerService) applicationContext.getBean("customerService");} catch (RuntimeException e) {e.printStackTrace();}}// 测试保存@Testpublic void testSaveForgin() {customerService.saveForgin();}// 测试获取关联对象的属性值// 两个sql,有外键方@Testpublic void testGetCustomer() {Customer customer = customerService.getCustomer(1);System.out.println(customer.getReferee().getName());}// 测试获取关联对象的属性值// 1条sql,无外键方@Testpublic void testGetReferee() {Referee referee = customerService.getReferee(1);System.out.println(referee.getCustomer().getName());}// 2条sql@Testpublic void testGetReferees() {for (Referee r : customerService.getReferees()) {System.out.println(r.getName());}}// 3条sql@Testpublic void testGetCustomers() {for (Customer c : customerService.getCustomers()) {System.out.println(c.getName());}}// 测试移除关联有关系// 维护端(外键方)可以维护关系 移除关联关系@Testpublic void testRemoveRelationForeign() {customerService.RemoveRelationForeign();}// 测试移除关联有关系// 被维护端(无外键方),无法维护关系 ,不可以维护关联关系,所以删除Referee时,// 如果有关联的Customer,就会抛异常 导致双方都删除不成功@Testpublic void testRemoveRelationNoForeign() {customerService.RemoveRelationNoForeign();}// 删除被维护端(无外键方),不能删除@Testpublic void testdeleteFromNoforeign() {customerService.deleteFromNoforeign();}// 删除维护端(有外键方),可以删除@Testpublic void testDeleeteForeignOne() {customerService.deleteFromForeign();}// 两个再时删除,先删除有维护端(有外键方),再删除被维护端(外键方)@Testpublic 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)@PrimaryKeyJoinColumnpublic 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@PrimaryKeyJoinColumnpublic 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")@Transactionalpublic class CustomerPrimaryService  {@Resourceprivate 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的idpublic 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;@BeforeClasspublic static void setUpBeforeClass() throws Exception {try {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");customerPrimaryService = (CustomerPrimaryService) applicationContext.getBean("customerPrimaryService");} catch (RuntimeException e) {e.printStackTrace();}}//测试保存@Testpublic 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());}//测试移除关系关系@Testpublic void testRemoveRelationPrimary(){customerPrimaryService.RemoveRelationPrimary();}//测试移除关系关系@Testpublic void testRemoveRelationNoPrimary(){customerPrimaryService.RemoveRelationNoPrimary();}//无外键方,不可以删除@Testpublic void testDeleteNoForeign(){customerPrimaryService.DeleteNoForeign();}// 有外键方 可以删除,删除是删除两个表的信息@Testpublic void testDeleteForeign(){customerPrimaryService.DeleteForeign();}//n+1条//测试获取列表信息@Testpublic void testGetCustomerPrimarys(){for(CustomerPrimary c:customerPrimaryService.getCustomerPrimarys()){System.out.println(c.getName());}}//n+1条//测试获取列表信息@Testpublic void testGetPrimaryReferees(){for(RefereePrimary r:customerPrimaryService.getRefereePrimarys()){System.out.println(r.getName());}}}
说明:本人于ITEYE创建于2013年,现转移到CSDN


0 0
原创粉丝点击