2020-09-01

JPA关联

1.JPA多表查询

多表查询在Spring DataJPA 中有两种实现方式,第一种是创建一个结果集的接口来接收多表查询后的结果,第二种是利用JPA的关联映射来实现。

多表连接查询

1.在entity包下创建一个SysRole 实体类和SysUser实体类

@Entity
@Table(name = "sys_user")
@Data
public class SysUser implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
  private long userId;
  @Column(name = "user_name")
  private String userName;
  @Column(name = "user_password")
  private String userPassword;
  @Column(name = "user_role_id")
  private long userRoleId;
  @Column(name = "user_flag")
  private Integer userFlag;
  //省略构造方法
@Entity
@Table(name = "sys_role")

public class SysRole implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "role_id")
  private long roleId;
@Column(name = "role_name")
  private String roleName;
@Column(name = "role_desc")
  private String roleDesc;
@Column(name = "role_flag")
  private Integer roleFlag;
  //省略构造方法

2.在vo包下创建一个UserInfo接口,里面提供所需数据的getter方法,其中包括用户数据和角色名称(roleName)

public interface UserInfo {
    public Long getUserId();
    public String getUserName();
    public String getUserPassword();
    public Long getUserRoleId();
    public Integer getUserFlag();
    //角色名称
    public String getRoleName();
}

3.在UserRepository中添加查询方法,返回值设置为UserInfo

public interface UserRepository extends JpaRepository<SysUser,Long> {
 @Query("SELECT u.userId as userId,u.userName as userName,u.userPassword as userPassword," +
            "u.userFlag as userFlag,u.userRoleId as userRoleId,r.roleName as roleName FROM " +
            "SysUser u,SysRole r WHERE u.userRoleId = r.roleId AND u.userId=?1")
    public UserInfo getUserInfo(Long id);
    }

注意:此处的HQL,必须向实体类和属性编写;获取到的属性必须指定别名;
4.测试验证

   @Test
    public void tsteGetUserInfo(){
        UserInfo userInfo = userRepository.getUserInfo(19L);
        System.out.println("userName:" +userInfo.getUserName());
        System.out.println("roleName:" +userInfo.getRoleName());
    }

结果:
在这里插入图片描述
第二种关联映射:

单向多对一关联

1.修改SysUser实体类,添加关联SysRole对象

@Entity
@Table(name = "sys_user")
@Data
public class SysUser implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
  private long userId;
  @Column(name = "user_name")
  private String userName;
  @Column(name = "user_password")
  private String userPassword;
//  @Column(name = "user_role_id")
//  private long userRoleId;
@ManyToOne(targetEntity = SysRole.class)
@JoinColumn(name = "user_role_id")
private SysRole sysRole;

  @Column(name = "user_flag")
  private Integer userFlag;

2.创建UserRepository

public interface UserRepository extends JpaRepository<SysUser,Long> {
}

3.测试

    @Test
    public void testGet() {
        SysUser sysUser = userRepository.findById(19L).get();
        System.out.println("userName:" +sysUser.getUserName());
        System.out.println("rolenName:" + sysUser.getSysRole().getRoleName());
    }

执行结果为:在这里插入图片描述
从输出的SQL语句可以发现,执行查询SysUser,关联查询了SysRole数据,并将SysRole相关联数据自动封装在SysUser对象的Role属性中。

双向一对多关联

1.修改SysRole实体类,添加关联的User对象集合

@Entity
@Table(name = "sys_role")

public class SysRole implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "role_id")
  private long roleId;
@Column(name = "role_name")
  private String roleName;
@Column(name = "role_desc")
  private String roleDesc;
@Column(name = "role_flag")
  private Integer roleFlag;
@OneToMany(targetEntity = SysUser.class,fetch = FetchType.LAZY,
        cascade = CascadeType.ALL,mappedBy = "sysRole")
private Set<SysUser> userSet = new HashSet<SysUser>();

修改过后的Role实体类中,新增了Set userSet 属性(使用Set 集合可避免重复对象的问题),用来表示一对多关联,在该属上,我们添加了@OneTOMany注解,映射一对多关联关系。
●targetEntity属性表示关联的实体类型
●fetch属性表示加载策略,FetchType 取值有LAZY 及EAGER, LAZY表示延迟加载,EAGER表示立即加载。@ManyToOne 注解也包含该属性,且默认值为EAGER,表示立即加载,所以查询User时通过左外关联立即获取Role数据; @OneToMany 注解该属性默认值为LAZY。
●cascade属性表示级联操作,CascadeType 取值有PERSIST、REMOVE、ALL… 等。PERSIST表示级联持久化(保存)操作,REMOVE 级联删除,ALL 级联所有操作。@ManyToOne注解也包含该属性,但一般不在多的一 方进 行级联操作。
●mappedBy属性用来设置对象之间的关系维护方(关系维护通过操作外键完成)。如不指定mappedBy属性,则对象均由自已维护关系(外键),操作一方对象时, 会额外产生更新外键的SQL语句。所以一般在@OneToMany注解中指定mappedBy属性,且属性值为多方对象中关联的一方属性名, 并且此时一方实体中不能添加@JoinColumn注解。
2、创建RoleRepository

public interface RoleRepository extends JpaRepository<SysRole,Long> {

}

3.测试查询

    @Test
    public void testGet1(){
        SysRole sysRole = roleRepository.findById(8L).get();
        System.out.println("roleName:" +sysRole.getRoleName());
       // System.out.println("users.size:"+sysRole.Users().size());
    }

在这里插入图片描述
4.测试级联操作:级联新增

 @Test
    public void testAdd(){
        //测试级联新增
        SysRole sysRole = new SysRole();
        sysRole.setRoleName("小强");
        sysRole.setRoleDesc("演示级联新增角色和用户");
        sysRole.setRoleFlag(1);
        SysUser sysUser = new SysUser();
        sysUser.setUserName("测试用户1");
        sysUser.setUserPassword("123456");
        sysUser.setSysRole(sysRole);
        sysUser.setUserFlag(1);
        SysUser sysUser2 = new SysUser();
        sysUser2.setUserName("测试用户2");
        sysUser2.setUserPassword("123456");
        sysUser2.setSysRole(sysRole);
        sysUser2.setUserFlag(1);
        sysRole.getUserSet().add(sysUser);
        sysRole.getUserSet().add(sysUser2);
        roleRepository.save(sysRole);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值