web-dev-qa-db-ja.com

JPAリポジトリクエリを結合で定義する方法

@Queryアノテーション付きのJpaリポジトリを使用して、結合クエリを作成したいと思います。

2つのテーブルがあります。

 table user 
 with iduser,user_name 

そして:

 table area 
 with idarea, area_name and iduser

ネイティブクエリは次のとおりです。

 SELECT
 u.user_name 
 FROM
  user as u 
  INNER JOIN area as a ON a.iduser = u.iduser
  WHERE
  a.idarea = 4

これで、テーブルHibernateエンティティのユーザーとエリアができました

だから私はUserRespositoryで試しました

@Query(SELECT  u.userName FROM  User u 
  INNER JOIN Area a ON a.idUser = u.idUser
  WHERE
  a.idArea = :idArea)
List<User> findByIdarea(@Param("idArea") Long idArea);

ログは言う:

予期しないトークン:

アイデアはありますか?

私のテーブルエンティティ

#User Table
@Entity
@Table(name="user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long idUser;
    private String userName;

    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="iduser")
    public Long getIdUser() {
        return idUser;
    }

    public void setIdUser(Long idUser) {
        this.idUser = idUser;
    }

    @Column(name="user_name")
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

#AREA table

@Entity
@Table(name="area")
public class Area  implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long idArea;
    private String areaName;
    private Long idUser;

    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="idarea")
    public Long getIdArea() {
        return idArea;
    }

    public void setIdArea(Long idArea) {
        this.idArea = idArea;
    }

    @Column(name="area_name")
    public String getAreaName() {
        return areaName;
    }

    public void setAreaName(String areaName) {
        this.areaName = areaName;
    }

    @Column(name="iduser")
    public Long getIdUser() {
        return idUser;
    }

    public void setIdUser(Long idUser) {
        this.idUser = idUser;
    }       
}
35
Shinigami

この問題は2つの理由で発生しています。

  • JPQLクエリが無効です。
  • 基礎となるJPQLクエリが利用できるエンティティ間の関連付けを作成していません。

JPQLで結合を実行する場合、結合しようとしているエンティティ間に基本的な関連付けが存在することを確認する必要があります。この例では、ユーザーエンティティとエリアエンティティ間の関連付けがありません。この関連付けを作成するには、Userクラス内にAreaフィールドを追加し、適切なJPAマッピングを確立する必要があります。以下にユーザーのソースを添付しました。 (マッピングをフィールドに移動したことに注意してください)

ser.Java

@Entity
@Table(name="user")
public class User {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="iduser")
    private Long idUser;

    @Column(name="user_name")
    private String userName;

    @OneToOne()
    @JoinColumn(name="idarea")
    private Area area;

    public Long getIdUser() {
        return idUser;
    }

    public void setIdUser(Long idUser) {
        this.idUser = idUser;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Area getArea() {
        return area;
    }

    public void setArea(Area area) {
        this.area = area;
    }
}

この関係が確立されると、@ Query宣言でエリアオブジェクトを参照できます。 @Queryアノテーションで指定されたクエリは、適切な構文に従う必要があります。つまり、on句を省略する必要があります。以下を参照してください。

@Query("select u.userName from User u inner join u.area ar where ar.idArea = :idArea")

あなたの質問を見ながら、ユーザーとエリアのエンティティ間の関係を双方向にしました。以下は、双方向の関係を確立するためのAreaエンティティのソースです。

Area.Java

@Entity
@Table(name = "area")
public class Area {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="idarea")
    private Long idArea;

    @Column(name="area_name")
    private String areaName;

    @OneToOne(fetch=FetchType.LAZY, mappedBy="area")
    private User user;

    public Long getIdArea() {
        return idArea;
    }

    public void setIdArea(Long idArea) {
        this.idArea = idArea;
    }

    public String getAreaName() {
        return areaName;
    }

    public void setAreaName(String areaName) {
        this.areaName = areaName;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}
57
Kevin Bowersox