Java持久化 OneToMany,ManyToOne,OneToOne,ManyToMany

工作中遇到的了,然后在网上也看了很多人写的,感觉挺乱的,自己梳理总结下;

1.OneToMany

分成两种,一种是双向的,一种是单向的;比如车(Car)和 车主(Owner),这里假设,一个车只能有一个车主,一个车主可以有多个车;双向的关系:通过车可以找到车对应的主人,而通过车主,可以获取到车主名下所有的车信息;而如果是单向的一对多的关系:通过车主可以找到车主名下的所有车,却不能通过车反过来找到对应的车主;这就是两者的区别;

1>单向的一对多的实现

数据库表结构

Owner Entity定义如下,其中cars中JoinColumn name属性指的是Car表的关联外键,这里是"owner_id",referencedColumnName是当前实体也就是Owner中的主键,这里是id;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @OneToMany
    @JoinColumn(name="owner_id", referencedColumnName="id")
    private Set<Car> cars = new HashSet<>();

这里如果不加JoinColumn的话,默认会使用一个中间表来处理的,我把这一行去掉之后,重新调用就报错了,如下图所示

说明默认的中间表是两者名字做了个连接,以下划线来分割;

Car Entity 是默认的定义,如下所示

public class Car implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "owner_id")
    private Long ownerId;

使用swagger来测试下,最终结果如图所示

2>双向一对多关系

实体的定义跟单向的有一些区别,如下所示

public class Owner implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "owner")
    private Set<Car> cars = new HashSet<>();

这里的mappedBy指的是Car实体中定义的Owner的对象名;Car实体定义如下所示

public class Car implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "owner_id")
    private Owner owner;

这里的JoinColumn中的name对应Car表中外键关联的owner_id;如果不指定JoinColumn的话,默认就是实体的名称_主键,所以这里去掉之后也是可以的;

还有一种方式是建立中间关联表的方式,表结构如图

实体如下所示

@Table(name = "owner")
public class Owner implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @OneToMany
    @JoinTable
        (
            name="OWNER_CARS",
            joinColumns={ @JoinColumn(name="ownerid", referencedColumnName="id") },
            inverseJoinColumns={ @JoinColumn(name="carid", referencedColumnName="id", unique=true) }
        )
    private Set<Car> cars = new HashSet<>();

这里的joinColumns指的连接的第一个表的信息,name指的关联表的列,referencedColumnName指的是对应实体的id;inverseJoinColumns指的是连接的第二个表的信息,name指的是关联表的列,referencedColumnName指的是列对应实体的id;

public class Car implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToOne
    @JsonIgnoreProperties("cars")    //这里需要注意加上,不然会有问题的
    private Owner owner;

2.OneToOne

假设1个车只有一个owner,一个owner只有一个车;

public class Owner implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;
public class Car implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @OneToOne
    @JoinColumn(name = "owner_id")
    private Owner owner;

这里的JoinColumn 中的name指的是Car表中关联的外键id;这样在获取Car信息的时候,就可以直接获取到owner的信息;

双向的oneToOne,entity如下所示

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

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @OneToOne
    @JoinColumn(name = "owner_id")
    private Owner owner;
public class Owner implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @OneToOne(fetch=FetchType.LAZY, mappedBy="owner")
    private Car car;

这里其中一个要指定mappedBy属性,标识Car实体中Owner属性的名称;这个接口返回如果都使用DTO后会有循环调用的问题,暂时没完美的解决办法;

https://en.wikibooks.org/wiki/Java_Persistence/OneToMany

https://en.wikibooks.org/wiki/Java_Persistence/ManyToOne

猜你喜欢

转载自blog.csdn.net/xiaoguangtouqiang/article/details/82746931