介紹@Query注釋之前,先看看怎么利用@NamedQuery進行命名查詢
1.現在實體類上定義方法已經具體查詢語句
@Entity @NamedQuery(name = "Task.findByTaskName", query = "select t from Task t where t.taskName = ?1") public class Task{ }
2.然后我們繼承接口之后,就可以直接用這個方法了,它會執行我們定義好的查詢語句並返回結果
public interface TaskDao extends JpaRepository<Task, Long> { Task findByTaskName(String taskName); }
試想一下,如果我們想自己定義執行查詢,利用命名查詢,顯然不行,因為,會在實體類上寫很多的@NamedQuery,這種情況的話,我們可以用@Query直接在方法上定義查詢語句,例如這樣
public interface TaskDao extends JpaRepository<Task, Long> { @Query("select t from Task t where t.taskName = ?1") Task findByTaskName(String taskName); }
@Query上面的1代表的是方法參數里面的順序,除了寫hql,我們還可以寫sql語句
public interface TaskDao extends JpaRepository<Task, Long> { @Query("select * from tb_task t where t.task_name = ?1", nativeQuery = true) Task findByTaskName(String taskName); }
在參數綁定上,我們還可以這樣子用
public interface TaskDao extends JpaRepository<Task, Long> { @Query("select t from Task t where t.taskName = :taskName and t.createTime = :createTime") Task findByTaskName(@Param("taskName")String taskName,@Param("createTime") Date createTime); }
當然在參數綁定上,我們還可以直寫問號
public interface TaskDao extends JpaRepository<Task, Long> { @Query("select t from Task t where t.taskName = ? and t.createTime = ?") Task findByTaskName(String taskName, Date createTime); }
再利用SpEL表達式,我們把實體類寫成動態的
public interface TaskDao extends JpaRepository<Task, Long> { @Query("select t from #{#entityName} t where t.taskName = ? and t.createTime = ?") Task findByTaskName(String taskName, Date createTime); }
這個的作用就是,當倆個實體類都有共同的父類的時候,例如這樣
// JPA 基類的標識 @MappedSuperclass @SuppressWarnings("serial") public abstract class IdEntity implements Serializable{ protected Long id; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long getId() { return id; } public void setId(Long id) { this.id = id; } } @Entity public class Task extends IdEntity{ } @Entity public class Project extends IdEntity{ }
然后有一個通用的接口
public interface GenericDao<T> extends JpaRepository<T, ID> { @Query("select t from #{#entityName} t where t.id= ?1") public T findById(Long id); }
再然后就taskDao和projectDao來繼承這個接口,這樣子的話,把公用的方法放在通用接口上,就不用重復寫方法了。
好,下面再說下,利用@Modifying進行更新
@Modifying @Query("update Task t set t.taskName = ?1 where t.id = ?2") int updateTask(String taskName, Long id);
在這里我們說下,spring data jpa的查詢策略,spring data jpa可以利用創建方法進行查詢,也可以利用@Query注釋進行查詢,那么如果在命名規范的方法上使用了@Query,那spring data jpa是執行我們定義的語句進行查詢,還是按照規范的方法進行查詢呢?看下查詢策略
查詢策略的配置可以在配置query-lookup-strategy,例如這樣
<jpa:repositories base-package="com.liuxg.**.dao" repository-impl-postfix="Impl" query-lookup-strategy = "create-if-not-found" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" > </jpa:repositories>
他有三種值可以配置
-
create-if-not-found(默認):如果通過 @Query指定查詢語句,則執行該語句,如果沒有,則看看有沒有@NameQuery指定的查詢語句,如果還沒有,則通過解析方法名進行查詢
-
create:通過解析方法名字來創建查詢。即使有 @Query,@NameQuery都會忽略
-
use-declared-query:通過執行@Query定義的語句來執行查詢,如果沒有,則看看有沒有通過執行@NameQuery來執行查詢,還沒有則拋出異常