복붙노트

[SPRING] Spring DATA JPA로 커스텀 질의 생성하기?

SPRING

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

이 목표를 달성 할 수있는 다른 방법이 있습니까? 미리 감사드립니다.

해결법

  1. ==============================

    1.불행히도 귀하의 접근 방식은 효과가 없습니다. @Query 어노테이션을 사용하는 경우 JPA 또는 메소드마다 고유 한 표기법으로 올바른 구체적인 쿼리를 제공합니다.

    불행히도 귀하의 접근 방식은 효과가 없습니다. @Query 어노테이션을 사용하는 경우 JPA 또는 메소드마다 고유 한 표기법으로 올바른 구체적인 쿼리를 제공합니다.

    매개 변수화 할 수있는 유일한 부분은 WHERE 절에 사용되는 값입니다. 공식 문서에서이 샘플을 고려하십시오.

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

    2.이것에 대한 특별한 지원은 없습니다. 하지만 String 매개 변수를 사용하여 사용자 정의 메소드를 작성하고 구현시 EntityManager를 주입하고 실행하는 것이 가능합니다.

    이것에 대한 특별한 지원은 없습니다. 하지만 String 매개 변수를 사용하여 사용자 정의 메소드를 작성하고 구현시 EntityManager를 주입하고 실행하는 것이 가능합니다.

    도움이 될만한 링크 :

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

    스프링 부트 및 스프링 데이터로 엔티티 관리자에 액세스하는 방법

    참고 : 저장소의 구현 세부 사항이 나머지 응용 프로그램으로 흘러 나오므로 수행하려는 작업이 좋은 아이디어인지 다시 생각해보십시오.

  3. ==============================

    3.나는이 부분에 대해 행동하기를 원한다. 네, @query 어노테이션을 사용하지 않고 그 일을 할 수있는 방법이 있습니다. 필요한 것은 JPA 저장소 인스턴스를 구현하는 인터페이스에서 파생 된 쿼리를 정의하는 것입니다.

    나는이 부분에 대해 행동하기를 원한다. 네, @query 어노테이션을 사용하지 않고 그 일을 할 수있는 방법이 있습니다. 필요한 것은 JPA 저장소 인스턴스를 구현하는 인터페이스에서 파생 된 쿼리를 정의하는 것입니다.

    저장소 인스턴스에서 다음과 같이 데이터베이스에서 CRUD 작업을 허용하는 모든 메소드에 노출됩니다.

     interface UserRepository extends CrudRepository<User, Long> {
    
     long deleteByLastname(String lastname);
    
     List<User> removeByLastname(String lastname);
    }
    

    이러한 방법으로 봄 데이터는 달성하려는 목표를 이해하고 적절하게 구현합니다.

    기본 CRUD 작업은 기본 클래스 정의에서 제공되므로 다시 정의 할 필요가 없습니다. 예를 들어 이것은 봄에 정의 된 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/에서 확인하십시오.

  4. ==============================

    4.@ jelies 대답을 바탕으로, 나는 다음과 같은 접근법을 사용하고있다.

    @ jelies 대답을 바탕으로, 나는 다음과 같은 접근법을 사용하고있다.

    MyQueryCustom 예제와 같이 사용자 정의 메서드에 대한 다른 인터페이스를 만든 다음 다음과 같이 구현할 수 있습니다.

    public class MyQueryRepositoryImpl implements MyQueryRepositoryCustom {
        @PersistenceContext
        private EntityManager entityManager;
    
        public int executeQuery(String query) {
            return entityManager.createNativeQuery(query).executeUpdate();
        }
    }
    

    이렇게하면 사용자 지정 쿼리가 실행됩니다.

  5. ==============================

    5.EntityManager를 사용하면이 작업을 수행 할 수 있습니다.

    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;
        }
    }
    

    그리고 당신의 질의는 "select id, roll_no = 1001 인 사용자로부터의 이름"입니다.

    여기서 쿼리는 ID와 이름 열이있는 객체를 반환합니다. 응답 클래스는 다음과 같습니다.

    응답 클래스는 다음과 같습니다.

    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 () 객체 배열을 반환합니다. 쿼리 열 위치를 사용하여 열 위치 및 데이터 형식을 유지 관리해야합니다.

    사용자가 선택한 ID, 이름 where roll_no = 1001

    쿼리는 배열을 반환하고 [0] -> id 및 1 -> name입니다.

    자세한 정보는이 스레드를 방문하십시오.

  6. from https://stackoverflow.com/questions/42966967/creating-a-custom-query-with-spring-data-jpa by cc-by-sa and MIT license