web-dev-qa-db-fra.com

Utilisation de @EmbeddedId avec JpaRepository

J'ai une classe Entitly simple avec le @EmbeddedId (champs Integer et String dans une classe distincte). Et j'utilise les données de printemps (org.springframework.data.jpa.repository.JpaRepository) pour accéder à la base de données (MySql), avec l'ID normal, les requêtes fonctionnent correctement, à la fois celles générées par Spring et celles écrites par moi-même. Avec le EmbeddedId je n'ai pas réussi à créer la bonne requête. Ce que je veux faire est de sélectionner tous les identifiants (l'un des champs de embeddedId pour lesquels une condition se produit) Ici, vous avez quelques exemples de code, peut-être que quelqu'un aura une idée de la façon de le résoudre.
La classe d'entité:

@Entity
@Table(name="table_name")
public class EntityClass {

    @EmbeddedId
    private EmbeddedIdClass id;
    private String  someField;
    //rest of implemetation
}

la classe EmbeddedId:

@Embeddable
public class EmbeddedIdClass implements Serializable {

public EmbeddedIdClass(Long id, String language) {
    super();
    this.id = id;
    this.language = language;
}

public UserAdTextId() {}        

@Column(name="ad_id", nullable=false)
    private Integer id;

    @Column(name="language_code", nullable=false)
    private String  language;
    //rest of implemetation
}

et le référentiel:

@Transactional(readOnly=true)
public interface MyRepository extends JpaRepository<EntityClass, EmbeddedIdClass> {
    @Query("select distinct ad_id from EntityClass where userId = :userId and (/*here the conditions*/)")
    public Page<Integer> findUserAdsWithSearchString(@Param("userId") Integer userId, @Param("searchString") String searchString, Pageable page);
//rest of implemetation
}

Je n'ai trouvé aucune documentation sur la façon de créer les méthodes pour prendre en charge @EmbeddedId, j'essayais de nombreux noms de méthode différents, mais je reçois toujours des exceptions de l'analyseur de méthode ..

34
Mat

Il semble que votre requête utilise des noms de colonne. Il doit contenir les noms des propriétés, y compris la navigation dans les objets intégrés. Il y a aussi une question connexe ici sur SO: Comment écrire JPQL SELECT avec l'identifiant intégré?

select distinct id.id from EntityClass where userId = :userId and (...)

Le premier id fait référence à l'attribut id de EntityClass (de type EmbeddedIdClass), et le second fait référence à la propriété id de EmbeddedIdClass.

Assurez-vous également qu'il existe une propriété userId dans EntityClass.

16
Xavi López

(par Yosi Lev) Cela peut être fait comme suit: Supposons que votre entité principale soit:

@Entity
@Table(name="JRULES_FLOW")
public class JrulesFlow implements Serializable {
   private static final long serialVersionUID = 1L;

   @EmbeddedId
   private JrulesFlowPK id;

   @Column(name="NEXT_SEQ")
   private int nextSeq;

   @Column(name="REF_ID")
   private String refId;

   @Column(name="TASK_TYPE")
   private String taskType;

   @Column(name="VALUE_TO_FIND")
   private String valueToFind;
}

Et votre classe PK est:

@Embeddable
public class JrulesFlowPK implements Serializable {
   //default serial version id, required for serializable classes.
   private static final long serialVersionUID = 1L;

   @Column(name="FLOW_ID")
   private String flowId;

   @Column(name="TASK_SEQ")
   private long taskSeq;
 }

Le nom de la méthode du référentiel JPA doit inclure le nom du champ id dans la classe principale suivi de la propriété que vous souhaitez interroger uppon dans la classe PK:

public interface JrulesFlowRepository extends JpaRepository<JrulesFlow, 
      JrulesFlowPK> { // NOTE: put here both classes - also the pk class..
   public List<JrulesFlow>  findByIdFlowId(String flowId);  // Id - is the 
                  // @EmbeddedId in JrulesFlow. FlowId is an attribute 
                  // within JrulesFlowPK
}
39
ylev