SpringData Jpa 方法命名查询和注解

1,238 阅读4分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

SpringDataJpa的方法命名查询

概述

只能根据jap的命名规则定义方法的名称去可以完成查询,jpa执行时就可以根据方法名创建相应的查询,查询时以FindBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。

我们下边简单写几个练习,只适合简单的一些查询 下边是官方的属性关键字

image.png

准备数据

image.png

实体类
@Entity
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "username")
    private String userName;
    private Integer age;
    private String address;
}
接口
public interface UserRepository extends JpaRepository<User,Integer> {

    //查询姓名
    List<User> findByUserNameLike(String userName);
    //查询大于多少岁
    List<User> findByAgeGreaterThan(Integer age);
    //查询名字和大于多少岁and
    List<User> findByUserNameLikeAndAgeGreaterThan(String userName,Integer age);
}
测试类

![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8b61c032a8cc4808b915725043f5c4cc~tplv-k3u1fbpfcp-watermark.image?)
@Autowired
private UserRepository userRepository;

@Test
public void test(){
    List<User> byUserNameLike = userRepository.findByUserNameLike("%王%");
    for (User user : byUserNameLike) {
        System.out.println(user);
    }
}

image.png

@Test
public void test2(){
    List<User> byAgeGreaterThan = userRepository.findByAgeGreaterThan(20);
    for (User user : byAgeGreaterThan) {
        System.out.println(user);
    }
}

image.png

@Test
public void test3(){
    List<User> userList = userRepository.findByUserNameLikeAndAgeGreaterThan("王", 20);
    for (User user : userList) {
        System.out.println(user);
    }
}

image.png

注解式查询

@Query

概述

@Query注解加JPQL语句完成查询

看下源码

nativeQuery() 默认为false 默认为JPQL语句,修改为true时,可以原生SQL,

如果你写了原生sql但是没有指定为true 他的语法检查时会报错的,其余的可以不关注,

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@QueryAnnotation
@Documented
public @interface Query {
   
    String value() default "";

    String countQuery() default "";

    String countProjection() default "";

    boolean nativeQuery() default false;

    String name() default "";

    String countName() default "";
}
接口
public interface UserQueryRepository extends JpaRepository<User,Integer> {

    @Query("from User  where userName like %?1%")
    List<User> QuertByNamelike(String userName);

    @Query("from User where userName like %?1% and age > ?2")
    List<User> QueryByNameAndAge(String username,Integer age);

    @Query(value = "select  * from user where username like %?1%",nativeQuery = true)
    List<User> queryByName1(String userName);

    @Query(value = "select  * from user where username like %?1% and age > ?2",nativeQuery = true)
    List<User> queryByNameAndAge1(String userName,Integer age);
}
测试类
@SpringBootTest
public class Test03 {

    @Autowired
    private UserQueryRepository userQueryRepository;

    @Test
    public void test1(){
        List<User> userList = userQueryRepository.QuertByNamelike("王");
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void test2(){
        List<User> userList = userQueryRepository.QueryByNameAndAge("王", 20);
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void test3(){
        List<User> userList = userQueryRepository.queryByName1("王");
        for (User user : userList) {
            System.out.println(user);
        }
    }
    @Test
    public void test4(){
        List<User> userList = userQueryRepository.queryByNameAndAge1("王", 20);
        for (User user : userList) {
            System.out.println(user);
        }
    }

}

@Param

接口
@Query(value = "select  * from user where username like %:name% and age > :age",nativeQuery = true)
List<User> queryByNameAndAge2(@Param("name") String userName,@Param("age") Integer age);
测试类
@Test
public void test5(){
    List<User> userList = userQueryRepository.queryByNameAndAge2("王", 20);
    for (User user : userList) {
        System.out.println(user);
    }
}
打印

image.png

@Modifying

@Modifying修改查询之更新

接口
@Modifying
@Query("UPDATE User set userName  = :username where id = :id")
void Update(@Param("username") String userName,@Param("id") Integer id);

@Modifying
@Query("delete from User  where id = :id")
void Delete(@Param("id") Integer id);
测试类
@Transactional
@Commit
@Test
public void test6(){
     userQueryRepository.Update("修改后1",9);
    userQueryRepository.Delete(4);
}

@Query的优缺点 优点

  • 1.可以灵活快速的使用JPQL和SQL
  • 2.对返回的结果和字段可以自定义
  • 3.支持连表查询和对象关联查询,可以组合出来复杂的SQL或者JPQL
  • 4.可以很好的表达你的查询思路
  • 5.灵活性非常强,快捷方便

缺点

  • 1.不支持动态查询条件,参数个数如果是不固定的不支持
  • 2.若将返回结果用Map或者Object[]数组接收结果,会导致调用此方法的开发人员不知道返回结果里面到底有些什么数据

Jpa注解的使用

基本注解@Entity、@Table、@Id、@GeneratedValue、@Basic、@Column、@Transient、@Lob、@Temporal

@Entity用于定义对象将会成为被JPA管理的实体,将字段映射到指定的数据库表中

@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
    String name() default "";
}

@TableTable用来定义entity主表的name,catalog,schema等属性。

@Id定义属性为数据库的主键,一个实体里面必须有一个,并且必须和@GeneratedValue配合使用和成对出现

@GeneratedValue 主键生成策略

@Column元数据定义了映射到数据库的列的所有属性:列名,是否唯一,是否允许为空,是否允许更新等。

@Transient表示该属性并不是一个到数据库表的字段的映射,指定的这些属性不会被持久化,ORM框架将忽略该属性

@Lob指定一个属性作为数据库支持的大对象类型在数据库中存储。使用LobType这个枚举来定义Lob是二进制类型还是字符类型。

@Temporal用来设置Date类型的属性映射到对应精度的字段。

@Basic表示属性是到数据库表的字段的映射。如果实体的字段上没有任何注解,默认即为@Basic。

@Transient表示该属性并非一个到数据库表的字段的映射,表示非持久化属性。JPA映射数据库的时候忽略它,与@Basic相反的作用