web-dev-qa-db-ja.com

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

この目標を達成できる他の方法はありますか。前もって感謝します

14
B378

パラメータ化できるのは、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);
}
23
ilya

ありがとう@ilya。 Spring Data JPAを使用してこのタスクを達成する代替アプローチはありますか? @Queryアノテーションなし?

この部分で行動したいだけです。はい、@ queryアノテーションを使用せずにそれについて進むことができる方法があります。必要なのは、JPAリポジトリインスタンスを実装するインターフェースから派生クエリを定義することです。

次に、リポジトリインスタンスから、データベースでのCRUD操作を許可するすべてのメソッドに公開されます。

 interface UserRepository extends CrudRepository<User, Long> {

 long deleteByLastname(String lastname);

 List<User> removeByLastname(String lastname);
}

これらのメソッドを使用すると、スプリングデータは、アーカイブしようとしているものを理解し、それに応じて実装します。

また、基本的な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/ のドキュメントをご覧ください。

1
Austine Gwa

これに対する特別なサポートはありません。ただし、できることは、Stringパラメーターを使用してカスタムメソッドを作成し、実装でEntityManagerをインジェクトして実行します。

おそらく役立つリンク:

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

スプリングブートおよびスプリングデータでエンティティマネージャーにアクセスする方法

注:リポジトリの実装の詳細がアプリケーションの残りの部分に流出するため、あなたがやろうとしていることが良いアイデアであるかどうかを再検討します。

1
Jens Schauder

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とname列を持つオブジェクトを返します。応答クラスは次のとおりです。

応答クラスは次のようなものです:

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、nameを選択します

queryは配列を返し、それは[0]-> idおよび 1 -> nameです。

詳細情報 このスレッド をご覧ください。

0

@jelies answer に基づいて、次のアプローチを使用しています

カスタムメソッド用に別のインターフェイスを作成し(MyQueryCustomの例として)、次のように実装できます。

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

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

これにより、カスタムクエリが実行されます。

0
B378