1.例子
@Transactional
public BasAccount findByAccount(String account) {
System.out.println(account);
Query q = em.createNativeQuery("{call QueryBasAccount(?)}",BasAccount.class);
q.setParameter(1, account);
List<BasAccount> list = q.getResultList();
BasAccount ba = null;
if(list.size()>0){
ba = (BasAccount)q.getResultList().get(0);
}
return ba;
}
2.語法
{call methodName(?)} Query .setParameter(1, param1);
{call methodName(?,?)} Query .setParameter(1, param1);Query .setParameter(2, param2);
3.createNativeQuery
概述:
在JPA 2.0 中我們可以使用entityManager.createNativeQuery()來執行原生的SQL語句。
但當我們查詢結果沒有對應實體類時,query.getResultList()返回的是一個List<Object[]>。
也就是說每行的數據被作為一個對象數組返回。
常見的用法是這樣的:
Query query = entityManager.createNativeQuery("select id, name, age from t_user");
List rows = query.getResultList();
for (Object row : rows) {
Object[] cells = (Object[]) row;
System.out.println("id = " + cells[0]);
System.out.println("name = " + cells[1]);
System.out.println("age = " + cells[2]);
}
總結:這樣用會使代碼非常不容易讓人理解, 究竟下標為0的元素到底是什么, 不去數查詢語句是不知道的,
而且一旦查詢語句被調整,Java代碼也要一起調整。這時候我們想如果返回的是Map的話,用起來會清晰的多。
query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
List rows = query.getResultList();
for (Object obj : rows) {
Map row = (Map) obj;
System.out.println("id = " + row.get("ID"));
System.out.println("name = " + row.get("NAME"));
System.out.println("age = " + row.get("AGE"));
}
4.createQuery與createSQLQuery(createNativeQuery)區別
第一點:前者用的hql語句進行查詢,后者可以用sql語句查詢 --也可以用實體
第二點:前者以hibernate生成的Bean為對象裝入list返回,后者則是以對象數組進行存儲
所以使用createSQLQuery有時候也想以hibernate生成的Bean為對象裝入list返回
例子:
@Override
public List<Commodity> findCommodityByActyId(int activityId) {
String sql = "SELECT aa.ACTIVITYSCOPE_VALUE from activity_scope aa LEFT JOIN activity_rule ar ON aa.ACTIVITYRULE_ID = ar.ACTIVITYRULE_ID LEFT JOIN"
+" activity ac on ar.ACTIVITY_ID = ac.ACTIVITY_ID where ac.ACTIVITY_ID ="+activityId+" and ac.status=3";
System.out.println(sql);
Query query = entityManager.createNativeQuery(sql);
List<Integer> commoditiyIds = (List<Integer>)(query.getResultList());
List<Commodity> commodities = new ArrayList<Commodity>();
for(int i=0;i<commoditiyIds.size();i++) {
String sql2 = "from Commodity c where c.commodityId=:c1";
Query query2 = entityManager.createQuery(sql2);
query2.setParameter("c1", commoditiyIds.get(i));
Commodity c = (Commodity) query2.getResultList().get(0);
commodities.add(c);
}
return commodities;
}
第三點:這兩種都是動態查詢,也不被緩存
5.自定義函數
//調用數據庫自定義函數
@Query(value="SELECT a FROM Client a WHERE function('DISTANCE',?1,?2,a.LONGITUDE,a.LATITUDE)<=2")
public List<Client> findNearClient(Float LONGITUDE,Float LATITUDE);
6.jpa通過解析方法名創建查詢和使用@Query創建自定義查詢
第一種: jpa通過解析方法名創建查詢:
JpaRepository會對Repository層所有未加@Query的方法名進行校驗,不符合規范會報錯,除非添加@Query注解;
查詢方法以find | read | get 開頭 ——建議統一用find開頭;
格式findBy**And/Or**;findBy**NotLike等,具體參考如圖:
例子:
List<User> findByUserName(String username);
User findByUserNameAndPassword(String username,String password);
注意:按方法名解析的查詢方法通常只適用於單表查詢,且建議where條件參數不多於三條的情況下,返回值通常上對應表的實體Bean,
通常用實體類List類型;具體要看返回結果,當返回值與類型不匹配時會造成查詢錯誤;
第二種:使用@Query創建自定義查詢
概述:@Query注解的使用非常簡單,只需在聲明的方法上面標注該注解,同時提供一個 JP QL查詢語句即可;
查詢策略:
<jpa:repositories>提供了guery-lookup-strategy 屬性,用以指定查找的順序。它有如下三 個取值:
第一:create-if-not-found: 如果方法通過@Query指定了查詢語句,
則使用該語句實現查詢, 如果沒有,則查找是否定義了符合條件的命名查詢,
如果找到,則使用該命名查詢,如果兩者都沒有找到,
則通過解析方法名字來創建查詢。這是query-lookup-strategy 屬性的默認值;
第二:create:通過解析方法名字來創建查詢。即使有符合的命名查詢,
或者方法通過@Query 指定的查詢語句,都將會被忽略;
第三:use-declared-query: 如果方法通過@Query指定了查詢語句,則使用該語句實現查詢,
如果沒有,則查找是否定義了符合條件的命名查詢,如果找到,則使用該命名查詢;
如果兩者都沒有找到,則拋出異常。
使用:
import com.xdja.timingDemo.model.Cert;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
import java.util.Optional;
public interface CertDao extends JpaRepository<Cert,Integer> {
//方法名解析JpaRepository<Cert,Integer> @Repository這兩個是重點
Optional<Cert> findById(Integer Id);
List<Cert> findAll();
@Query(value = "select expire_date_time from Cert where time < '1609344000'")
List<Date> findAllDate();
@Modifying //DML操作需添加該注解
@Query(value = "delete from Cert where time < '1609344000'")
void deleteTime();
@Modifying
@Query(value = "update Cert set status = 0 where time < '1550645979'")
void updateStatus();
@Modifying
@Query(value = "update Cert set status = 0 where time < :time ")
void updateStatusByTime(@Param("time") Long time);
}
學習來源:https://www.cnblogs.com/LittleDirewolf/p/5121626.html
https://blog.csdn.net/qq_31678877/article/details/52935942
http://www.voidcn.com/article/p-vhqlnady-po.html
//@query自定義函數
https://blog.csdn.net/qq_33296651/article/details/89027914
//解析方法名的查詢
https://blog.csdn.net/weixin_42209368/article/details/87918285