JPQL manyToMany 单向查询

Posted

技术标签:

【中文标题】JPQL manyToMany 单向查询【英文标题】:JPQL manyToMany unidirectional query 【发布时间】:2015-09-11 22:55:30 【问题描述】:

我一直在论坛和各处寻找单向多对多查询。我找到了很多例子,但我无法真正根据自己的需要调整它们:(

我有 2 个实体类(动漫和用户)

Anime 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "anime_id")
    private Integer id;

    //Other fields etc.


User 
    @Id
    @ValidUsername
    @Column(name = "user_id")
    private String username;

    @ManyToMany()
    @JoinTable(name = "users_animes",
        joinColumns = @JoinColumn(name = "anime_id", referencedColumnName =     "anime_id"),
        inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "user_id"))
    private final List<Anime> animes = new ArrayList<>();

Anime 只是保存来自动画的数据。 用户持有用户的用户名等和他订阅的动漫列表。

现在我正在尝试查找一个查询,让我可以获取该列表中的所有动漫。 它在表中映射为“users_animes”。

因为我对 JPQL 还很陌生,所以这将是一个巨大的帮助。

谢谢!

【问题讨论】:

【参考方案1】:

这是一个简单的例子。假设我们有 Country Entity,它可以有多个 Citizen:

@Entity
@Table (name = "countries")
public class Country implements Serializable 

    @Id
    @Column (name = "coun_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column (name = "country_name")
    private String countryName;

    @ManyToMany (cascade = CascadeType.ALL)
    @JoinTable (
            name = "citizen_country",
            joinColumns = @JoinColumn (name = "country_id", referencedColumnName = "coun_id"),
            inverseJoinColumns = @JoinColumn (name = "citizen_id", referencedColumnName = "cit_id")
    )
    private List<Citizen> citizens;

    public Country() 
    public Country(String countryName) 
        this.countryName = countryName;
    
    //getters and setters

还有Citizen,可以属于多个国家:

@Entity
@Table (name = "citizens")
public class Citizen implements Serializable 

    @Id
    @Column (name = "cit_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column (name = "country_name")
    private String citizenName;

    public Citizen() 

    public Citizen(String citizenName) 
        this.citizenName = citizenName;
    

    public void setId(Long id)  this.id = id; 
    public Long getId()  return id; 

    public void setCitizenName(String citizenName)  this.citizenName = citizenName; 
    public String getCitizenName()  return citizenName; 

    //getters and setters

它是单向的,就像你想要的那样。因此,Citizen Entity 不知道 Country,因此您无法直接获取某个 Citizen 属于哪个 Country 的信息。但是,您可以检索有关哪些公民属于某个国家/地区的信息。

更进一步,您可以填充表格:

    Citizen citizen1 = new Citizen("Smith");
    Citizen citizen2 = new Citizen("Kowalski");
    Citizen citizen3 = new Citizen("Muller");
    dataAccess.saveCitizen(citizen1);
    dataAccess.saveCitizen(citizen2);
    dataAccess.saveCitizen(citizen3);

    // now let's fetch them from DB, along with their other properties (only id in this case)
    citizen1 = dataAccess.getCitizenByName("Smith");
    citizen2 = dataAccess.getCitizenByName("Kowalski");
    citizen3 = dataAccess.getCitizenByName("Muller");

    Country country1 = new Country("Foo");
    Country country2 = new Country("Bar");

    // create lists to hold citizens for each country
    List<Citizen> citizenList1 = new ArrayList();
    List<Citizen> citizenList2 = new ArrayList();

    // add elements to the lists
    citizenList1.add(citizen1);
    citizenList1.add(citizen2);        
    citizenList2.add(citizen2);
    citizenList2.add(citizen3);

    //assign lists of citizens to each country
    country1.setCitizens(citizenList1);
    country2.setCitizens(citizenList2);

    //save data in DB
    dataAccess.saveCountry(country1);
    dataAccess.saveCountry(country2);

    //fetch list of all persisted countries (associated Citizens will come along)
    countries = dataAccess.getAllCountries();

最后:

@Stateless
public class DataAccess 

    @PersistenceContext
    EntityManager em;

    public void saveCountry(Country country) 
        em.persist(country);
    

    public void saveCitizen(Citizen citizen) 
        em.persist(citizen);
    

    public Citizen getCitizenByName(String name) 
        Query query = em.createQuery("SELECT c FROM Citizen c WHERE c.citizenName = :name");
        query.setParameter("name", name);
        return (Citizen) query.getSingleResult();
    

    public List<Country> getAllCountries() 
        Query query = em.createQuery("SELECT c FROM Country c");
        return (List<Country>) query.getResultList();
    



【讨论】:

难道不能通过 JOIN 查询从某个用户那里获取我想要的动画吗?还是只有在我从用户那里得到一个对象时才可能通过获取用户并获取列表。 我不确定我是否理解你的问题。我试图让 JPQL 尽可能简单,让 JPA Provider 完成其余的工作。您想获取与用户关联的所有动漫,对吗?只需将我的示例中的 Country 替换为您的 User 和 Citizen 即可。

以上是关于JPQL manyToMany 单向查询的主要内容,如果未能解决你的问题,请参考以下文章

多对多查询 jpql

JPQL 查询中的@OrderColumn

JPQL 用于单向 OneToMany

JPQL 查询:属于多个类别的项目

ManyToMany 属性的 SELECT 上的 JPQL Hibernate SQLException

JPQL 基于条件的多对多连接