采坑系列之JPA查询

springboot-jpa


最近在研究Spring的jpa的动态查询,使用比较方便,但是着实也踩了不少的坑,简单的总结一下。

  • JPA简介
    Java Persistence API(JPA),是一组用于将数据存入数据库的类和方法的集合,为POJO提供持久化标准规范,通过注解格式声明,用于定义实体类映射到关系数据表的规则。
    本人描述不够到位,具体可以参考官方详细说明
    jpa动态查询案例参考说明 –注意版本号,代码书写是有变化的
  • 使用idea+maven

    pom文件添加依赖如下:

        <!--jpa-spec动态查询-->
        <dependency>
            <groupId>com.github.wenhao</groupId>
            <artifactId>jpa-spec</artifactId>
            <version>2.2.1</version>
        </dependency>

两个关联表(User和Address)配置:

引用lombok依赖便可以利用注解省略setter和getter方法,下面代码是两个关联表多对多,一对多或多对一可以参考上面的案例参考,里面会有详细的介绍,本人主要是在多对多模式入坑,所以主要分析这部分:

  • 首先需要在两个实体类里面声明彼此,多对多模式就彼此声明了彼此的数组(如果是一对多或多对一,只声明多的一方为数组即可),主要不同的就是两个类的注解不同,具体请往下看:
@Setter
@Getter
@Entity
@Table(name = "user")
public class User implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "user_id")
    private Integer userId;
    @Column(name = "name")
    private String name;
    @Column(name = "sex")
    private String sex;
    @Column(name = "birthday")
    private Date birthday;
    @Column(name = "height")
    private String height;

    @ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    @JoinTable(name = "user_addresses",
            joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "address_id",referencedColumnName = "address_id")})
    private List<Address> addresses;
}
@Entity
@Table(name = "address")
@Setter
@Getter
public class Address implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "address_id")
    private Integer addressId;
    @Column(name = "address_name")
    private String addressName;

    @ManyToMany(fetch = FetchType.LAZY,mappedBy = "addresses")
    @JsonIgnore
    private List<User> users;
}
  • 两个实体类都需在声明的数组上添加@ManyToMany的注解,该注解可添加属性,如cascade是关于级联操作的属性设置;fetch是关于加载方式的属性设置,LAZY表示懒加载,EAGER表示立即加载;mappedBy表示当前类放弃字段维护权,即放弃控制关联关系,不能使用@JoinColumn等表示关联的注解;@JsonIgnore注解是多个表关联查询必不可少的,防止关联类进行多次的重复查询;未设置 mappedBy的一方控制关联关系,需通过添加@JoinTable注解来确定关联表及关联字段,该注解必填属性,name表示关联表的名称,joinColumns是主操作表的中间表列,即维护端字段,而inverseJoinColumns是副操作表的中间表列,referencedColumnName 标注的是所关联表中的字段名,若不指定则使用的所关联表的主键字段名作为外键。

  • 实体类的注解介绍完毕,现在就开始进行数据的查询,首先继承JpaRepository,里面有封装好代码,可以通过方法名进行数据的操纵。

@Repository
public interface UserRepository extends JpaRepository<User,Integer> {}
  • 前面声明引入的jpa-spec依赖到此开始正式派上用场,Specification中包含很多语法,模糊查询、区间查询等,本次只是使用的准确查找,目的是讲解使用的坑,具体可自行研究。服务层代码如下:
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List<User> manyToMany(Integer id){
//        3.0版本的写法
//        Specification<Address> specification = Specifications.<Address> and()
//                .eq("addresses.addressId",id)
//                .build();
        //当前版本的写法
        Specification<User> specification = new Specifications<User>()
//              .eq("userId",id)       
                .eq("addresses.addressId",id)
                .build();
        return userRepository.findAll(specification);
    }
}
  • 代码的维护端是User,即本人理解是从User发起的多对多的查询,如果查询的是维护端的属性,则直接填写相应的实体类属性名称(注意:不是表字段),如果查询的条件是关联类的属性,需要进行限定,即mappedBy中定义的关联类名称.属性名称,如“addresses.addressId”。

  • 最后就是进行最后的结果验收了,入口代码如下:

@GetMapping("/ManyToMany")
    public List<User> manyToMany(Integer id){
        return userService.manyToMany(id);
    }
  • 查询的结果如下:

    数据结果

  • 本人在使用过程中遇到的坑如下:

    名称不符
    这里写图片描述

    多次循环查询问题(@JsonIgnore)
    这里写图片描述

  • 说明:本人通过亲身体验,按照自己的习惯去理解和使用动态查询,如有不对的地方请多多指教!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值