简体   繁体   English

使用哪个联接操作将多个表与JPA / SQL查询结合在一起?

[英]Which join operation to use to combine several tables with JPA/SQL query?

I have a JPA database setup like the following: 我有一个如下的JPA数据库设置:

@Entity
public class Contact {

    @Id
    private Long id;
    @Column(length = 64)
    private String firstname;
    @Column(length = 64)
    private String surname;

    @OneToMany(mappedBy = "contact") 
    private List<Address> adresses = new ArrayList<Address>();
    @OneToMany(mappedBy = "contact") 
    private List<Telephone> telephones = new ArrayList<Telephone>();

}

@Entity
public class Address {

    @Id
    private Long id;
    @Column(length = 128)
    private String street;
    @Column(length = 16)
    private String plz;


    @ManyToOne 
    private Contact contact;

}

@Entity
public class Telephone {

    @Id
    private Long id;
    @Column(length = 32)
    private String number;


    @ManyToOne
    private Contact contact;

}

Now I have the following query for my search form: 现在,我对搜索表单有以下查询:

em.createQuery("SELECT DISTINCT c FROM Contact c LEFT JOIN c.addresses a LEFT JOIN c.telephones t "
                        + "WHERE c.surnameLIKE '%"+var_surname+"%' "
                        + "AND c.firstname LIKE '%"+var_firstname+"%' "
                        + "AND a.street LIKE '%"+var_street+"%'"
                        + "AND t.nummer LIKE '%"+var_telephone+"%'"
                        ).getResultList();

My question is now how can I join all 3 tables in a single JPA-query to look up for the firstname, street and number for example? 现在的问题是,如何在一个JPA查询中联接所有3个表,例如查找名字,街道和电话号码? I tried already with LEFT JOIN, but I don't get any results when for example the Telephone table is empty (it properly works if all tables have appropriate entries). 我已经尝试过使用LEFT JOIN,但是例如在Telephone表为空时(如果所有表都有适当的条目,它就可以正常工作),但没有得到任何结果。 I would like to have a result list with the Contacts even when there are no phone numbers and just one result even if a contact has more than one phone number for example. 即使没有电话号码,我也希望有一个包含联系人的结果列表,例如,即使一个联系人有多个电话号码,我也只有一个结果。

Many thanks for your help in advance. 非常感谢您的提前帮助。

Did you try using "LEFT OUTER JOIN" eg below? 您是否尝试过使用下面的“ LEFT OUTER JOIN”?

           "SELECT DISTINCT c FROM Contact c LEFT OUTER JOIN c.addresses a LEFT OUTER JOIN c.telephones t "
          + "WHERE c.surnameLIKE '%"+var_surname+"%' "
          + "AND c.firstname LIKE '%"+var_firstname+"%' "
          + "AND a.street LIKE '%"+var_street+"%'"
          + "AND t.nummer LIKE '%"+var_telephone+"%'"
          ).getResultList();

The DISTINCT should remove the duplicates, DISTINCT应该删除重复项,

for getting results if there is no relationship you need to use an OR, 为了获得结果(如果没有关系),您需要使用OR,

      + "AND ((a.id is null) OR (a.street LIKE '%"+var_street+"%'))"

Thanks for your helpful answers. 感谢您的帮助。 Finally I had to solve the problem with a dynamic buildup of my search string, selectively add/remove some parts of the join operands depending on which fields the user left empty. 最后,我不得不通过动态构建搜索字符串来解决该问题,根据用户将哪些字段留空,有选择地添加/删除联接操作数的某些部分。

    public List<Person> querySearch(String snachname, String svorname, String srechtsform, String sadresse, String sort, String sland, String stelefon, String semail, LoadGroup group) {
        if(srechtsform.equals("Alle")) {
            srechtsform = "";
        }
        if(sland.equals("Alle")) {
            sland = "";
        }
        String q = "SELECT DISTINCT * FROM Person p LEFT OUTER JOIN Adresse a ON (a.PERSON_ID=p.ID) LEFT OUTER JOIN Telefon t ON (t.PERSON_ID=p.ID) LEFT OUTER JOIN Email e ON (e.PERSON_ID=p.ID) WHERE p.nachname1 LIKE '%"+snachname+"%'AND p.vorname LIKE '%"+svorname+"%' AND p.rechtsform LIKE '%"+srechtsform+"%' ";
        if(sadresse.equals("") && sort.equals("") && sland.equals("")) {
            q += "AND (a.ID IS NULL OR (a.strasse LIKE '%"+sadresse+"%' AND a.ort LIKE '%"+sort+"%' AND a.land LIKE '%"+sland+"%')) "; 
        } else {
            q += "AND a.strasse LIKE '%"+sadresse+"%' AND a.ort LIKE '%"+sort+"%' AND a.land LIKE '%"+sland+"%' "; 
        }
        if(stelefon.equals("")) {
            q += "AND (t.ID IS NULL OR t.nummer LIKE '%"+stelefon+"%') ";
        } else {
            q += "AND t.nummer LIKE '%"+stelefon+"%' ";
        }
        if(semail.equals("")) {
            q += "AND (e.ID IS NULL OR e.mailadresse LIKE '%"+semail+"%') ";
        } else {
            q += "AND e.mailadresse LIKE '%"+semail+"%' ";
        }
        q += "GROUP BY p.ID";
        Query query = em.createNativeQuery(q, Person.class);
        if(group!=null) { query.setHint(QueryHints.LOAD_GROUP, group); }
        return query.getResultList();
    }

"LEFT OUTER JOIN a ON b" style syntax is not supported in JPA (see http://chrisiecorner.blogspot.fi/2012/12/jpa-and-outer-joins.html ) JPA不支持“ LEFT OUTER JOIN a ON b”样式语法(请参阅http://chrisiecorner.blogspot.fi/2012/12/jpa-and-outer-joins.html

You must do native query. 您必须执行本机查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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