Hibernate一对一关联映射(注解)
2016-04-10 18:13
597 查看
hibernate一对一关联映射有两种方式,一种是基于外键方式(常用),一种是基于主键方式
一、首先我们来看基于外键一对一关联映射:
1.数据表关联映射图
基于外键的一对一关联映射,维护端(有外键方)可以维护双方关联,对双方进行删除操作,而被维护端(无外键方)则不可以
2.Customer实体类,维护端(有外键方)
二、基于主键一对一关联映射
基于主键一对一关联,双方都不可以维护关联(不如基于外键的一对一关联),有外键方可以进行删除(双方都删除),无外键方不能进行删除
1.数据表关联映射图
2.CustomerPrimary实体类,关联维护端(有外键方)
3. RefereePrimary实体类:关系被维护端(无外键方)
4.CustomerPrimaryService服务类
一、首先我们来看基于外键一对一关联映射:
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
相关文章推荐
- java连接MYSQL
- File类常用API学习
- eclipse安装maven
- 点滴积累
- modSecurity和Naxsi哪个更适合Nginx搭建WAF
- 最大子段和【模板】
- ViewPager实现程序引导界面
- 程序猿怎样变身IT讲师
- Linux内核分析作业7:Linux内核如何装载和启动一个可执行程序
- [算法 basic]----排序算法
- 读收获不止oracle--表设计有感
- Vector和Set类
- mysql中运算符小结
- 真机运行、手机运行、真机联调常见问题
- Two Sum
- 通达OA 公共文件柜二次开发添加管理信息(图文)
- Log4Net使用详解1
- Eclipse上安装GIT插件EGit
- 挖坟字符串知识点
- 杨辉三角的数组实现