事件的起因
事源是这样的,由于jpa没有更新单一字段的方法,只能够手写sql语句来进行更新,既然如此为何不写在数据库中的存储过程里面呢?
于是就写了一个存储过程。
CREATE DEFINER=`root`@`localhost` PROCEDURE `p1_delete_article`(IN `a_id` int)
BEGIN
UPDATE tb_article
SET is_delete=1
WHERE article_id = a_id;
END
接下来使用jpa来调用存储过程。
//data object
@NamedStoredProcedureQueries({
@NamedStoredProcedureQuery(name = "deleteArticle",procedureName = "p1_delete_article",
parameters = {@StoredProcedureParameter(name = "articleId",mode = ParameterMode.IN,type = Integer.class)})
})
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "tb_article")
@EntityListeners(AuditingEntityListener.class)
public class Article {
...
}
//service层
@PersistenceContext
private EntityManager em;
@Override
public Boolean deleteArticle(Integer id){
StoredProcedureQuery query = em.createNamedStoredProcedureQuery("deleteArticle")
.setParameter("articleId",id);
return query.execute();
}
然后前端调用这个接口无论如何都返回False!
分析错误
查找源码,发现调用的是ProcedureCallImpl里面的execute方法:
@Override
public boolean execute() {
try {
final Output rtn = outputs().getCurrent();
return rtn != null && ResultSetOutput.class.isInstance( rtn );
}
catch (NoMoreReturnsException e) {
return false;
}
catch (HibernateException he) {
throw getExceptionConverter().convert( he );
}
catch (RuntimeException e) {
getProducer().markForRollbackOnly();
throw e;
}
}
查找ProcedureCallImpl实现的接口StoreProcedureQuery来看看解释:
/**
* Return true if the first result corresponds to a result set,
* and false if it is an update count or if there are no results
* other than through INOUT and OUT parameters, if any.
* @return true if first result corresponds to result set
* @throws QueryTimeoutException if the query execution exceeds
* the query timeout value set and only the statement is
* rolled back
* @throws PersistenceException if the query execution exceeds
* the query timeout value set and the transaction
* is rolled back
*/
boolean execute();
只有返回的第一个结果是resultSet的话,就return true。如果返回的是update count(应该是update影响的行数)或者没有其他结果除了通过INOUT和OUT参数得到的话,就return false。
因为我调用的存储过程是update,所以一直return false 了。
测试正确方法使用execute方法
测试一下return true的情况:
ResultSet是数据中查询结果返回的一种对象,可以说结果集是一个存储查询结果的对象,但是结果集并不仅仅具有存储的功能,他同时还具有操纵数据的功能,可能完成对数据的更新等。
因此编写一个新的存储过程:
CREATE DEFINER=`root`@`localhost` PROCEDURE `p_test`()
BEGIN
#Routine body goes here...
SELECT * FROM tb_article;
END
jpa调用这个存储过程:
//实体类
@NamedStoredProcedureQuery(name = "findAll",procedureName = "p_test",
resultClasses = {Article.class}
//调用这个存储过程
@Override
public Boolean deleteArticle(Integer id){
StoredProcedureQuery query = em.createNamedStoredProcedureQuery("findAll");
return query.execute();
}
这时候在前端可以获得结果为true:
版权声明:本文为weixin_41006725原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。