一)SpringData(双向)一对一配置

1.1)使用到的注解

1.@OneToOne:表示一对一的关系

public @interface OneToOne {
    Class targetEntity() default void.class;//目标实体类

    CascadeType[] cascade() default {};//级联策略

    FetchType fetch() default FetchType.EAGER;//加载关系

    boolean optional() default true;//表示是否出现空值,默认是允许出现空值的
    //此属性一般定义在被拥有方,指向的是拥有方中拥有的被拥有方的属性名
    String mappedBy() default "";//关联关系的域,如果是单向关联着不需要,多项则需要,设置的关系外键

    boolean orphanRemoval() default false;// 是否允许孤儿删除
}

2.@JoinColum :表示关系的外键列,注解出现在那方,表示那方维护外键

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JoinColumn {
    String name() default "";//外键名称

    String referencedColumnName() default "";//此属性设置的是当前外键列,引用的是哪个的表的主键

    boolean unique() default false;//是否唯一

    boolean nullable() default true;//是否当前列可以为空

    boolean insertable() default true;//是否可插入 使用默认值即可

    boolean updatable() default true;//是否可修改

    String columnDefinition() default "";// 列定义

    String table() default ""; //表

    ForeignKey foreignKey() default @ForeignKey; //表示当前@JoinColumn 标识的是个外键
}

3.级联关系类型
1.CascadeType.REMOVE
Cascade remove operation,级联删除操作。
删除当前实体时,与它有映射关系的实体也会跟着被删除。
2.CascadeType.MERGE
Cascade merge operation,级联更新(合并)操作。
当Student中的数据改变,会相应地更新Course中的数据。
3.CascadeType.DETACH
Cascade detach operation,级联脱管/游离操作。
如果你要删除一个实体,但是它有外键无法删除,你就需要这个级联权限了。它会撤销所有相关的外键关联。
4.CascadeType.REFRESH
Cascade refresh operation,级联刷新操作。
假设场景 有一个订单,订单里面关联了许多商品,这个订单可以被很多人操作,那么这个时候A对此订单和关联的商品进行了修改,与此同时,B也进行了相同的操作,但是B先一步比A保存了数据,那么当A保存数据的时候,就需要先刷新订单信息及关联的商品信息后,再将订单及商品保存。
5.CascadeType.ALL
Cascade all operations,清晰明确,拥有以上所有级联操作权限

package javax.persistence;

public enum CascadeType {
    ALL,//拥有全部级联操作
    PERSIST,//级联新增
    MERGE,//级联更新
    REMOVE,//级联删除
    REFRESH,//级联刷新
    DETACH;//级联脱离,脱离外键关系

    private CascadeType() {

1.2)需求

1.用户和角色:一个用户只允许一个角色,一个角色只允许一个用户(双向一对一)
2.模拟双向一对一的注解配置
用户

/**
 * @project_name:hibernate02
 * @date:2019/8/19:16:21
 * @author:shinelon
 * @Describe:
 */
@Entity //实体类
@Table(name = "t_user") //映射数据库的表名
public class Users implements Serializable {

    /**
    ID增长策略
     * TABLE:使用一个特定的数据库表格来保存主键。
     * SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
     * IDENTITY:主键由数据库自动生成(主要是自动增长型)
     * AUTO:主键由程序控制。
    */
    @Id//表示表的主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)//id自增长
    @Column(name = "userid")
    private Integer userid;


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

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

  
    @OneToOne(cascade = CascadeType.PERSIST)//设置级联关系
    @JoinColumn(name = "role_id")//外键列的名称
    private Roles roles;

角色

@Entity
@Table(name = "t_roles")
public class Roles {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "roleid")
    private Integer roleid;

    @Column(name = "roleName")
    private String roleName;
    //引入就是关联那
    @OneToOne(mappedBy = "roles")//只有在双向关联中才会使用,表示当前的角色数据那个用户,
    private Users users;
@Autowired
private UserDaoFive userDaoFive;

@Test
public void test1() {
    Users users = new Users();
    users.setUsername("GGG");
    users.setPassword("333");
    Roles roles = new Roles();
    roles.setRoleName("Manager");
    //设置关联关系
    users.setRoles(roles);
    roles.setUsers(users);
    //保存的时候现在保存不维护

    this.userDaoFive.save(users);

}

成功插入数据

spring mongodb data 关联查询 springdatajpa关联查询_外键

1.3)双项关联查询
利用Hibernate的导航查询
测试

/**
 * 双线关联导航查询
 */
@Test
public void test3() {
    Users one = this.userDaoFive.findOne(12);
    System.out.println(one);
    System.out.println(one.getRoles());
}

spring mongodb data 关联查询 springdatajpa关联查询_一对一_02

1.3)单向一对一测试

首先是测试结果,生成的SQL语句上是没有任何区别的

spring mongodb data 关联查询 springdatajpa关联查询_一对一_03

角色

package com.sxt.pojo;

import javax.persistence.*;

/**
 * @project_name:hibernate02
 * @date:2019/8/21:10:21
 * @author:shinelon
 * @Describe:
 */
@Entity
@Table(name = "t_roles")
public class Roles {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "roleid")
    private Integer roleid;

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

//    @OneToOne(mappedBy = "roles")//表示一对一,引入当前关联方属于那个,如果是双向关联则需要注解,反之则无
//    private Users users;

用户

@Entity //实体类
@Table(name = "t_user") //映射数据库的表名
public class Users implements Serializable {

    @Id//表示表的主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)//id自增长
    @Column(name = "userid")
    private Integer userid;


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

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

    @OneToOne(cascade = CascadeType.PERSIST)//设置级联关系
    @JoinColumn(name = "role_id")//外键列的名称
    private Roles roles;

测试单向关联

/**
 * 测试单向关联
 */
@Test
public void test2() {
    Users users = new Users();
    users.setUsername("FFF");
    users.setPassword("444");
    Roles roles = new Roles();
    roles.setRoleName("Common");
    //设置关联关系
    users.setRoles(roles);
    //roles.setUsers(users);
    this.userDaoFive.save(users);

双向关联和单向关联的区别

现在试想一个场景,一辆车和一个车牌,这是典型的一对一的关系,一个车只能有一个的车牌不允许出现套牌多个车牌的情况,那么如果此时车发生了事故,车逃逸,却留下了一个车牌,那么我们就可以根据车牌找到这个的车,此时车和车牌就是双向关联的关系,我们可以通过车找到车牌,也可以通过车牌找到具体的车,但是如果是单向的话,我们只能通过车找到车牌,但是无法通过车牌找到车。(实际要根据具体的实体类配置)
上面的单向就是这个的道理,用户和角色是一对一的情况,那么必须保证一个角色只能属于一个用户,我们可以通过用户找到角色,也可以通过角色找到用户,此时就是双向,因为不管在Users实体还是Roles实体都有相互的引用。
注意在双向关联中toString方法要注意不能两个都出现打印拥有对象的情况,不然会出现相互调用toString方法出现内存溢出
双向关联对一对多也是同样适用的。