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;
- }
- }
- @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;
- }
- }
- @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); //如果这里不想一个对象一个对象保存,想要级联自动保存,需要在保存的对象那一方添加cascade=CascadeType.ALL来级联保存操作
- 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();
- }
- }
- 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);
- }
- }
- 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());
- }
- }
- }