【Spring Data 系列學習】Spring Data JPA @Query 註解查詢

【Spring Data 系列學習】Spring Data JPA @Query 註解查詢

前面的章節講述了 Spring Data Jpa 經過聲明式對數據庫進行操做,上手速度快簡單易操做。但同時 JPA 還提供經過註解的方式實現,經過將 @Query 註解在繼承 repository 的接口類方法上 。java

Query 源碼講解git

public @interface Query {
    /**
    * 指定 JPQL 的查詢語句。(nativeQuery = true)是原生的 SQL 語句.
    */
    String value() default "";
    /**
    * 指定 count 的 JPQL 語句,若是不指定將根據 query 自動生成。
    * (nativeQuery = true 的時候,是原生查詢的 SQL 語句)
    */
    String countQuery() default "";
    /**
    *根據那個字段來 count,通常默認便可。
    */
    String countProjection() default "";
    /**
    * 默認是 false,表示 value 裏面是否是原生的 SQL 語句
    */
    boolean nativeQuery() default false;
    /**
    * 能夠指定一個 query 的名字,必須是惟一的。
    * 若是不指定,默認的生成規則是
    * {$domainClass}.${queryMethodName}
    */
    String name() default "";
    /**
    * 能夠指定一個 count 的query 名字,必須是惟一的。
    * 若是不指定,默認的生成規則是:
    * {$domainClass}.${queryMethodName}.count
    */
    String countName() default "";
}

快速上手

項目中的pom.xmlapplication.properties與 Chapter1 相同github

實體類映射數據庫表spring

user 實體類sql

@Entity
@Table(name = "t_user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

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

    @Column(name ="u_age")
    private Integer age;
    
    @Column(name ="u_email")
    private String email;

    // 省略構造器 set/get        

}

@Entity:定義對象將會成爲被JPA管理的實體,將映射到指定的數據庫表。數據庫

@Table :指定數據庫的表名。app

@Column:定義該屬性對應數據庫中的列名。dom

@Id 定義屬性爲數據庫的主鍵,一個實體裏面必須有一個。學習

@GeneratedValue(strategy = GenerationType.IDENTITY) 自增加 ID 策略測試

生成以下:

image-20200301143239501

@Query 查詢

基本使用

繼承 UserQueryRepository

public interface UserQueryRepository extends JpaRepository<User, Long> {

    /**
     *  語句中 User 查詢數據表的類名,?1 括號表明第一個參數
     */
    @Query(name = "select  * from User where name = ?1")
    List<User> findByName(String name);

     /**
     * Sort 排序
     *  根據姓名模糊查詢排序
     */
    @Query("select u from User u where u.name like ?1%")
    List<User> findByAndSort(String name, Sort sort);
    
    /**
     * @Transactional 事務的支持 ,@Modifying 用於修改查詢
     * @param name 對應 ?1
     * @param id 對應 ?2
     * @return
     */
    @Transactional
    @Modifying
    @Query("update User u set u.name = ?1 where u.id = ?2")
    int updateById(String  name, Long id);


}

@Param用法

/**
     *  param 對象
     * @param name
     * @param age
     * @return
     */
    @Query(value = "select  u from User u where u.name = :name and u.age = :age")
    List<User> queryParamByNameAndAge(@Param("name") String name,@Param("age") Integer age);


    /**
     *  傳一個對象
     * @param user
     * @return
     */
    @Query(value = "select  u from User u  where u.name = :#{#user.name} and u.age = :#{#user.age}")
    List<User> queryObjectParamByNameAndAge(@Param("user") User user);
  • :name 對應 @Param中的 name。
  • :age 對應 @Param中的 age。

  • :#{#user.name} : 對象中的參數使用方法

SpEL表達式

@Query("select u from #{#entityName} u where u.lastname = ?1")
 List<User> findByLastname(String lastname);
  • entityName: 根據指定的 Repository 自動插入相關的 entityName。有兩種方式能被解析出來:
    • 若是定義了 @Entity 註解,直接用其屬性名。
    • 若是沒有定義,直接用實體類的名稱。

原生 SQL

@Query(value = "select * from t_user  where u_name = :name",nativeQuery = true)
    List<User> queryNativeByName(@Param("name") String name);
  • nativeQuery: 爲 true 開啓。開啓以後字段則須要對應的數據庫中的表名和字段。

CURD 測試類

路徑:src/test/java/com/mtcarpenter/repository/UserQueryRepositoryTest.java

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserQueryRepositoryTest {

    /**
     * ⽇志對象
     */
    private Logger logger = LoggerFactory.getLogger(UserQueryRepositoryTest.class);

    @Autowired
    private UserQueryRepository userQueryRepository;


    @Before
    public void save() {
        logger.info("新增數據 result = {}", userQueryRepository.save(new User("小米", 9, "a@qq.com")));
        logger.info("新增數據 result = {}", userQueryRepository.save(new User("張三", 16, "b@qq.com")));
        logger.info("新增數據 result = {}", userQueryRepository.save(new User("三哥", 12, "c@qq.com")));
        logger.info("新增數據 result = {}", userQueryRepository.save(new User("米二", 13, "e@qq.com")));
        logger.info("新增數據 result = {}", userQueryRepository.save(new User("阿三", 12, "f@qq.com")));
        logger.info("新增數據 result = {}", userQueryRepository.save(new User("張三", 12, "g@qq.com")));
        logger.info("新增數據 result = {}", userQueryRepository.save(new User("米二", 8, "h@qq.com")));
    }

    /**
     * 基本使用
     */
    @Test
    public void test() {
        logger.info("@query 查詢張三 result = {}", userQueryRepository.findByName("張三"));
        logger.info("根據姓名模糊查詢排序 result = {}", userQueryRepository.findByNameAndSort("米", new Sort(Sort.Direction.ASC,"age")));
        logger.info("修改 id = 1 的name ,result ={ }", userQueryRepository.updateById("紅米", 1L));
    }

    /**
     *  param 參數使用
     */
    @Test
    public void paramTest(){
        logger.info("@param 使用方法  result = {}",userQueryRepository.queryParamByNameAndAge("張三", 12));
        User user = new User();
        user.setName("張三");
        user.setAge(12);
        logger.info("@Param 對象 result = {}", userQueryRepository.queryObjectParamByNameAndAge(user));
    }

    /**
     * SpEl 使用
     */
    @Test
    public void spELTest(){
        logger.info("SpEL 使用方法  result = {}",userQueryRepository.queryELByName("張三"));
    }

    /**
     * 原生查詢
     */
    @Test
    public void nativeTest(){
        logger.info("原生查詢 使用方法  result = {}",userQueryRepository.queryNativeByName("張三"));

    }
}

本章代碼

相關文章
相關標籤/搜索