使用Spring DATA JPA创建自定义查询?

时间:2017-03-23 03:54:13

标签: mysql sql spring spring-data spring-data-jpa

我正在使用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

还有其他办法,我可以实现这个目标。提前致谢

6 个答案:

答案 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并执行它。

可能有用的链接:

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations

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的唯一记录。它将起作用