JPA调用存储过程
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