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


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

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

Query 源碼講解

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 相同

實體類映射數據庫表

user 實體類

@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 :指定數據庫的表名。

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

@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("張三"));

    }
}

本章代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM