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

在上一篇,也就是Hibernate关系映射(一)中已经介绍了一对一单向外键关联,本篇介绍一对一双向外键关联


首先还是来构造一个实际应用的场景,比如实体类车辆(Car),它具有以下属性:Id,品牌(brand),车牌(lisencePlate);实体类车牌(LisencePlate),它具有以下属性:Id,号码(number),所属车辆(car)。那么车辆和车牌是一对一的关系,一辆车只能有一个车牌,一个车牌也只能属于一辆车,不允许套牌,典型的一对一关系,依然是根据PowerDesigner反向工程反向出来的表结构如图:
这里写图片描述
car这个表中有一个字段lisencePlate_id作为外键指向了lisence_plate表的主键id字段。

重点内容
看表结构,单向关联的表结构和双向关联的表结构在数据库中的表示是一致的,但是单向关联和双向关联的区别在于,双向关联,你可以用car.getLisencePlate来找到该车辆的车牌,也可以用lisencePlate.getCar来找到该车牌所属车辆,但是单向关联只能从车找到车牌,或者从车牌找到车。


下面是实体类:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="car")
public class Car {

    private Integer id;
    private String brand;
    private LisencePlate lisencePlate;

    public Car() {
        super();
    }

    public Car(Integer id, String brand, LisencePlate lisencePlate) {
        super();
        this.id = id;
        this.brand = brand;
        this.lisencePlate = lisencePlate;
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }

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

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    @OneToOne
    public LisencePlate getLisencePlate() {
        return lisencePlate;
    }

    public void setLisencePlate(LisencePlate lisencePlate) {
        this.lisencePlate = lisencePlate;
    }

}

每一个使用到的标签的含义在上一篇介绍过了,这里不再赘述。

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="lisence_plate")
public class LisencePlate {
    private Integer id;
    private String number;
    private Car car;

    public LisencePlate() {
        super();
    }

    public LisencePlate(Integer id, String number, Car car) {
        super();
        this.id = id;
        this.number = number;
        this.car = car;
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }

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

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @OneToOne(mappedBy="lisencePlate")
    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

}

注意:双向关联,那么在车牌类中也需要一个属性,所属车辆(car),设置上get和set方法后,在get方法上有这么一个标签@OneToOne(mappedBy=”lisencePlate”),@OneToOne表示车牌和车辆也是一对一的关系并且关联上车辆,mappeBy表示被谁映射,并且mappedBy应该存在于“被拥有方”,指向“拥有方”,那么指向拥有方应该指向车辆类,mappedBy=”lisencePlate”表示指向车辆类的lisencePlate属性,表示被lisencePlate属性映射,并且lisencePlate是主导。
重点内容
双向关联必须设置mappedBy
最后在hibernate.cfg.xml配置文件中设置上实体的映射就可以了

        <!-- 一对一双向外键关联 -->
        <mapping class="com.ht.entity.one2one.bi.fk.Car"/>
        <mapping class="com.ht.entity.one2one.bi.fk.LisencePlate"/>

下面来看CRUD的测试,首先测试添加新数据testCreate()方法

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import com.ht.entity.one2one.bi.fk.Car;
import com.ht.entity.one2one.bi.fk.LisencePlate;



public class One2OneTest2 {

    private static SessionFactory sessionFactory;

     @BeforeClass
     public static void beforeClass() {
       sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
     }
     @AfterClass
     public static void afterClass() {
      sessionFactory.close();
     }

     @Test
     public void testCreate(){
      Session session = sessionFactory.getCurrentSession();
      session.beginTransaction();

      Car car = new Car();
      car.setBrand("Jeep Grand Cherokee");

      LisencePlate lisencePlate = new LisencePlate();
      lisencePlate.setNumber("云A 12345");

      car.setLisencePlate(lisencePlate);
      lisencePlate.setCar(car);

      session.save(lisencePlate);
      session.save(car);

      session.getTransaction().commit();
     }

结果如图:

Hibernate: 
    insert 
    into
        lisence_plate
        (number) 
    values
        (?)
Hibernate: 
    insert 
    into
        car
        (brand, lisencePlate_id) 
    values
        (?, ?)

这里写图片描述
这里写图片描述


接下来测试数据读取,testRead()方法

     @Test
     public void testRead(){
         Session session = sessionFactory.getCurrentSession();
         session.beginTransaction();

         Car car = (Car) session.load(Car.class, 1);
         System.out.println(car.getBrand()+"  "+car.getLisencePlate().getNumber());

         LisencePlate lisencePlate = (LisencePlate) session.load(LisencePlate.class, 1);
         System.out.println(lisencePlate.getNumber()+"  "+lisencePlate.getCar().getBrand());

         session.getTransaction().commit();
     }

这里就体现了双向关联和单向关联的区别,双向关联可以从车辆找到车牌信息,也可以从车牌找到所属车辆的信息。

Hibernate: 
    select
        car0_.id as id2_1_,
        car0_.lisencePlate_id as lisenceP3_2_1_,
        car0_.brand as brand2_1_,
        lisencepla1_.id as id3_0_,
        lisencepla1_.number as number3_0_ 
    from
        car car0_ 
    left outer join
        lisence_plate lisencepla1_ 
            on car0_.lisencePlate_id=lisencepla1_.id 
    where
        car0_.id=?
Hibernate: 
    select
        car0_.id as id2_1_,
        car0_.lisencePlate_id as lisenceP3_2_1_,
        car0_.brand as brand2_1_,
        lisencepla1_.id as id3_0_,
        lisencepla1_.number as number3_0_ 
    from
        car car0_ 
    left outer join
        lisence_plate lisencepla1_ 
            on car0_.lisencePlate_id=lisencepla1_.id 
    where
        car0_.lisencePlate_id=?


Jeep Grand Cherokee  云A 12345
云A 12345  Jeep Grand Cherokee

下面测试修改数据,testUpdate()方法

     @Test
     public void testUpdate(){
         Session session = sessionFactory.getCurrentSession();
         session.beginTransaction();

         Car car = (Car) session.load(Car.class, 1);
         car.setBrand("Jeep大切诺基");

         LisencePlate lisencePlate = (LisencePlate) session.load(LisencePlate.class, 1);
         lisencePlate.setNumber("云A 66666");


         session.saveOrUpdate(car);
         session.saveOrUpdate(lisencePlate);

         session.getTransaction().commit();
     }

结果如下:

Hibernate: 
    update
        lisence_plate 
    set
        number=? 
    where
        id=?
Hibernate: 
    update
        car 
    set
        lisencePlate_id=?,
        brand=? 
    where
        id=?

这里写图片描述
这里写图片描述


最后是删除操作,testDelete()方法,一样的,如果只是删除车牌,那么就要先解除该车牌和所属车辆之间的约束

     @Test
     public void testDelete(){
         Session session = sessionFactory.getCurrentSession();
         session.beginTransaction();

         Car car = (Car) session.load(Car.class, 1);

         LisencePlate lisencePlate = (LisencePlate) session.load(LisencePlate.class, 1);

         car.setLisencePlate(null);
         session.delete(lisencePlate);

         session.getTransaction().commit();
     }

结果如下:

Hibernate: 
    update
        car 
    set
        lisencePlate_id=?,
        brand=? 
    where
        id=?
Hibernate: 
    delete 
    from
        lisence_plate 
    where
        id=?

这里写图片描述
这里写图片描述


希望对你所有帮助,下一篇介绍多对一的单向关联

[上一篇 Hibernate关系映射(一)一对一单向外键关联@OneToOne Annotation方式](http://blog.csdn.net/murcielagoan/article/details/43954727

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Hibernate是一个Java持久化框架,它能够将Java对象映射到数据库中的格,同时支持各种关系数据库,如MySQL、Oracle等。在Hibernate中,对于一对一、一对多和多对多的关系,我们可以通过以下方式进行映射一对一关系:在Hibernate中,可以通过主键关联外键关联来实现一对一关系映射。主键关联是指两个实体之间的关联通过主键来进行,可以使用@PrimaryKeyJoinColumn注解将两个实体关联起来。外键关联是指通过一个实体引用另一个实体的主键作为外键,使用@JoinColumn注解来指定外键属性。 一对多关系:在Hibernate中,一对多关系通常通过外键关联来实现。在一的一方,使用@OneToMany注解来定义一对多关系,同时使用@JoinColumn注解指定外键属性。在多的一方,使用@ManyToOne注解来定义多对一关系,并使用@JoinColumn注解指定外键属性。 多对多关系:在Hibernate中,多对多关系通常通过中间来实现。在多对多的两个实体中,使用@ManyToMany注解来定义多对多关系。同时,需要在中间中创建两个外键,分别与两个实体的主键关联,并使用@JoinTable注解来指定中间名和两个外键的列名。 总结:通过Hibernate的注解方式,可以方便地实现一对一、一对多和多对多关系映射。通过合理地使用注解,可以减少编写映射文件的工作量,提高开发效率。同时,Hibernate还提供了在运行时自动生成结构的功能,可以根据Java实体类来动态创建或更新对应的数据库格,从而提高系统的可维护性和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值