【Spring Data 系列學習】Spring Data JPA @Query 註解查詢 前面的章節講述了 Spring Data Jpa 通過聲明式對資料庫進行操作,上手速度快簡單易操作。但同時 JPA 還提供通過註解的方式實現,通過將 註解在繼承 repository 的介面類方法上 。 Qu ...
【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.xml
、application.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 策略
生成如下:
@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, "[email protected]")));
logger.info("新增數據 result = {}", userQueryRepository.save(new User("張三", 16, "[email protected]")));
logger.info("新增數據 result = {}", userQueryRepository.save(new User("三哥", 12, "[email protected]")));
logger.info("新增數據 result = {}", userQueryRepository.save(new User("米二", 13, "[email protected]")));
logger.info("新增數據 result = {}", userQueryRepository.save(new User("阿三", 12, "[email protected]")));
logger.info("新增數據 result = {}", userQueryRepository.save(new User("張三", 12, "[email protected]")));
logger.info("新增數據 result = {}", userQueryRepository.save(new User("米二", 8, "[email protected]")));
}
/**
* 基本使用
*/
@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("張三"));
}
}