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

j2datikz  于 2022-12-26  发布在  Spring
关注(0)|答案(6)|浏览(191)

我正在使用Spring Data JPA进行一个项目,我在数据库中有一个表my_query。
我想创建一个以字符串作为参数的方法,然后在数据库中将其作为查询执行。
方法:

executeMyQuery(queryString)

举个例子当我通过

queryString= "SELECT * FROM my_query"

那么它应该在数据库级别运行该查询。
存储库类如下所示。

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

有没有其他的方法,我可以达到这个目标?

vjrehmav

vjrehmav1#

其中唯一可以参数化的部分是WHERE子句中使用的值。请考虑官方文档中的以下示例:

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
  User findByEmailAddress(String emailAddress);
}
wlsrxk51

wlsrxk512#

使用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,name from users where 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-〉name。
更多信息请访问this thread

shstlldc

shstlldc3#

对于这个没有特殊的支持,但是你可以创建一个带有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
注意:如果您尝试做的是一个好主意,我会重新考虑,因为它会将存储库的实现细节渗透到应用程序的其余部分。

jjjwad0x

jjjwad0x4#

如果要添加自定义查询,应该添加@Param

@Query("from employee where name=:name")    
employee findByName(@Param("name)String name);
}

这查询将选择唯一的记录与匹配name .这将工作

zfciruhq

zfciruhq5#

谢谢你@ilya。有没有一种替代方法可以使用SpringDataJPA来完成这个任务?没有@Query注解?
我只想处理这一部分。是的,有一种方法可以不使用@query注解来处理它。您需要的是从实现JPA存储库示例的接口定义一个派生查询。
然后,从存储库示例中,您将看到允许对数据库执行CRUD操作的所有方法,例如

interface UserRepository extends CrudRepository<User, Long> {

 long deleteByLastname(String lastname);

 List<User> removeByLastname(String lastname);
}

有了这些方法,spring data将理解你试图归档的内容,并相应地实现它们。
还要记住,基本的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/上的文档

xzlaal3s

xzlaal3s6#

根据@jelies的回答,我使用以下方法
您可以为自定义方法创建另一个接口(* 如MyQueryCustom*),然后按如下所示实现它。

public class MyQueryRepositoryImpl implements MyQueryRepositoryCustom {
    @PersistenceContext
    private EntityManager entityManager;

    public int executeQuery(String query) {
        return entityManager.createNativeQuery(query).executeUpdate();
    }
}

这将执行自定义查询。

相关问题