简体   繁体   中英

How to write query on many to many association table

I have 2 entities and I have a many to many relation between them. I want to write a query on the association table.

Here are the two entities. Craftsmen and Skill.
I want to write a query which selects all Craftsmen with a given skill. 

    @Entity
    @Table(name = "craftsman")
    public class Craftsman {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;

        @ManyToMany
        @JoinTable(name = "craftman_skill", joinColumns = @JoinColumn(name = "craftman_id", referencedColumnName = "id"), 
            inverseJoinColumns = @JoinColumn(name = "skill_id", referencedColumnName = "id"))
        private List<Skill> skillList;
    }
        @Entity
        @Table(name = "skill")
        public class Skill {
            @ManyToMany(mappedBy = "skillList")
            @JsonBackReference
            private List<Craftsman> craftmanList;
        }

Here is what I have tried:

@Query("SELECT c FROM Craftsman c JOIN c.skillList sl WHERE c.skillList.skill_id = :skillId")
    public List<Craftsman> getCraftsmanBySkill(@Param("skillId") Long skillId);

Here is the query that works in MySql: This gets all craftsman who has the skill with id 1:

select c.name from craftsman c, craftman_skill cs 
where cs.craftman_id = c.id 
and cs.skill_id = 1;

Here is the errors I get:

Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: skill_id of: com.craftsmen.crafts.persistence.Skill [SELECT c FROM com.craftsmen.crafts.persistence.Craftsman c JOIN c.skillList sl WHERE c.skillList.skill_id = :skillId ]
Caused by: org.hibernate.QueryException: could not resolve property: skill_id of: com.craftsmen.crafts.persistence.Skill [SELECT c FROM com.craftsmen.crafts.persistence.Craftsman c JOIN c.skillList sl WHERE c.skillList.skill_id = :skillId ]

I guess the problem is, that your Skill entity indeed does not have a skill_id, or better, an id .

Have you tried to give your Skill entity an id

@Entity
@Table(name = "skill")
public class Skill {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;

   @ManyToMany(mappedBy = "skillList")
   @JsonBackReference
   private List<Craftsman> craftmanList;
}

reference it in your Craftsman entity

@Entity
@Table(name = "craftsman")
public class Craftsman {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToMany
    @JoinTable(name = "craftman_skill", joinColumns = @JoinColumn(name = "craftman_id", referencedColumnName = "id"), 
        inverseJoinColumns = @JoinColumn(name = "skill_id", referencedColumnName = "id"))
    private List<Skill> skillList;
}

and then change the Query to

SELECT c FROM Craftsman c JOIN c.skillList sl WHERE sl.id = :skillId

That should do the trick.

Also you can consider option to use JpaRepository here:

public interface CraftsmanRepository extends JpaRepository<Craftsman, String> {
    public List<Craftsman> getBySkillListIn(@NotEmpty List<Skill> skillList);

}

What it means, that Jpa, by writting method name already maps the query to SQL query for your (try it if you have not)

And at the end of the method "In" means that it should check not one value but multiple values

In SQL In also works and does something as:

where <condition> And <>condition And <condition> And...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM