我正在使用Spring Data JPA开展项目。我在数据库中有一个表作为my_query。
我想创建一个方法,该方法将字符串作为参数,然后在数据库中将其作为查询执行。
方法:
executeMyQuery(queryString)
例如,当我通过
时queryString= "SELECT * FROM my_query"
然后它应该在DB级别运行该查询。
存储库类如下。
public interface MyQueryRepository extends JpaRepository<MyQuery, Long>{
public MyQuery findById(long id);
@Modifying(clearAutomatically = true)
@Transactional
@Query(value = "?1", nativeQuery = true)
public void executeMyQuery(String query);
}
然而,它没有像我预期的那样起作用。它给出了以下错误。
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''select * from my_query;'' at line 1
还有其他办法,我可以实现这个目标。提前致谢
答案 0 :(得分:19)
不幸的是,你的方法不起作用。如果使用@Query
注释,则按JPA或本机表示法提供一个正确的具体查询。
您可以参数化的唯一部分是WHERE
子句中使用的值。请考虑official doc中的此示例:
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
User findByEmailAddress(String emailAddress);
}
答案 1 :(得分:1)
对此没有特别的支持。但是你可以做的是创建一个带有String
参数的自定义方法,并在你的实现中注入EntityManager
并执行它。
可能有用的链接:
How to access entity manager with spring boot and spring data
注意:我会重新考虑你想要做的是一个好主意,因为它会将存储库的实现细节渗透到应用程序的其余部分。
答案 2 :(得分:1)
谢谢@ilya。是否有其他方法可以使用Spring Data JPA完成此任务?没有@Query注释?
我只想对这一部分采取行动。是的,有一种无需使用@query注释即可解决此问题的方法。您需要的是从实现JPA存储库实例的接口定义派生查询。
然后从您的存储库实例中,您将获得所有允许对数据库执行CRUD操作的方法,例如
interface UserRepository extends CrudRepository<User, Long> {
long deleteByLastname(String lastname);
List<User> removeByLastname(String lastname);
}
使用这些方法,spring数据将了解您要归档的内容并相应地实现它们。
还请记住,基本CRUD操作是从基类定义中提供的,您无需重新定义它们。例如,这是spring定义的JPARepository类,因此对其进行扩展可以为您提供所有方法。
public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> {
<S extends T> S save(S entity);
Optional<T> findById(ID primaryKey);
Iterable<T> findAll();
long count();
void delete(T entity);
boolean existsById(ID primaryKey);
}
有关更多最新信息,请查看https://docs.spring.io/spring-data/jpa/docs/current/reference/html/上的文档
答案 3 :(得分:0)
使用EntityManager,您可以实现这一目标。
假设您的实体类像下面这样:
import javax.persistence.*;
import java.math.BigDecimal;
@Entity
@Table(name = "USER_INFO_TEST")
public class UserInfoTest {
private int id;
private String name;
private String rollNo;
public UserInfoTest() {
}
public UserInfoTest(int id, String name) {
this.id = id;
this.name = name;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", nullable = false, precision = 0)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
@Column(name = "name", nullable = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Basic
@Column(name = "roll_no", nullable = true)
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
您的查询是“ 选择id,roll_no = 1001的用户的名字”。
此处查询将返回带有id和name列的对象。您的Response类如下:
您的Response类是:
public class UserObject{
int id;
String name;
String rollNo;
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
在这里,UserObject构造函数将获取一个对象数组并使用该对象设置数据。
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
您的查询执行功能就像下面这样:
public UserObject getUserByRoll(EntityManager entityManager,String rollNo) {
String queryStr = "select id,name from users where roll_no = ?1";
try {
Query query = entityManager.createNativeQuery(queryStr);
query.setParameter(1, rollNo);
return new UserObject((Object[]) query.getSingleResult());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
您必须在这里导入以下软件包:
import javax.persistence.Query;
import javax.persistence.EntityManager;
现在您的主类,您必须调用此函数。首先获取EntityManager并调用此getUserByRoll(EntityManager entityManager,String rollNo)
函数。调用过程如下:
这是进口商品
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
通过以下方式获取EntityManager
:
@PersistenceContext
private EntityManager entityManager;
UserObject userObject = getUserByRoll(entityManager,"1001");
现在您的userObject中有数据。
注意:
query.getSingleResult()
返回一个对象数组。您必须使用查询列位置来维护列位置和数据类型。
从其中roll_no = 1001的用户中选择ID,名称
查询返回一个数组,它是[0]-> id和1->名称。
更多信息,请访问this thread。
答案 4 :(得分:0)
基于@jelies answer,我正在使用以下方法
您可以为自定义方法创建另一个接口(例如MyQueryCustom 作为),然后按如下所示实现它。
public class MyQueryRepositoryImpl implements MyQueryRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
public int executeQuery(String query) {
return entityManager.createNativeQuery(query).executeUpdate();
}
}
这将执行自定义查询。
答案 5 :(得分:0)
如果要添加自定义查询,则应添加@Param
@Query("from employee where name=:name")
employee findByName(@Param("name)String name);
}
此查询将选择匹配项name
的唯一记录。它将起作用