【问题标题】:JPA query in multiple tables with many-to-many relationship具有多对多关系的多个表中的 JPA 查询
【发布时间】:2016-07-22 06:04:53
【问题描述】:

共有三个表:HospitalMedical_ServiceLanguage_Service, 医院可提供医疗服务和语言服务。所以有两个多对多关系。

Simple ERD

现在我想用postcode = 3000medical service = Emergency 搜索医院数据。

DaoImpl:

public List<Hospital> findByPostcodeAndMedicalType(String postcode, String medical) {
        String str = "SELECT h FROM Hospital h INNER JOIN Medical_Service m ON h.hospital_id = m.hospital_id WHERE " 
                + "h.Postcode = :postcode AND m.Medical_name = :medical";
        Query query = em.createQuery(str);
        query.setParameter("postcode", postcode);
        query.setParameter("medical", medical);
        return query.getResultList();

    }

另外,如果我想从三个表中按邮政编码、医疗类型和语言进行搜索,如何写一个jsql。

警告:

错误:org.hibernate.hql.internal.ast.ErrorCounter - 预期加入的路径! 预计加入的路径! 在 org.hibernate.hql.internal.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalker.java:378) 在 org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3858) 在 org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3644)

2016 年 4 月 2 日晚上 10:54:30 org.apache.catalina.core.StandardWrapperValve 调用 严重:servlet [appServlet] 在路径 [/travel] 的上下文中的 Servlet.service() 引发异常 [请求处理失败;嵌套异常是 java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: Postcode of: com.health.entity.Hospital [SELECT h FROM com.health.entity.Hospital h INNER加入 Medical_Service m ON h.hospital_id = m.hospital_id WHERE h.Postcode = :postcode AND m.Medical_name = :medical]] 与根本原因 org.hibernate.QueryException:无法解析属性:邮政编码:com.health.entity.Hospital 在 org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:83) 在 org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:77) 在 org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1978) 在 org.hibernate.hql.internal.ast.tree.FromElementType.getPropertyType(FromElementType.java:367)

Hospital.class

@Entity
@Table(name = "Hospital")
public class Hospital {

@Id
@GeneratedValue
    private int hospital_id;

    private String hospital_name;

    private String postcode;

    private String suburb;

    private String address;

    private String type;

    private String category;

    private String longitude;

    private String latitude;

    private String email;

    private String website;

    private String phoneno;

    private String isemergency;

    private String agencytype;

    private String fax;

    @ManyToMany
    @JoinTable(
        name = "Hospital_Medical",
        joinColumns=@JoinColumn(name="Hospital_id", referencedColumnName="Hospital_id"),
        inverseJoinColumns=@JoinColumn(name="Medical_id", referencedColumnName="Medical_id"))
private List<MedicalService> services;

    @ManyToMany
    @JoinTable(
        name = "Hospital_Language",
        joinColumns=@JoinColumn(name="Hospital_id", referencedColumnName="Hospital_id"),
        inverseJoinColumns=@JoinColumn(name="Language_id", referencedColumnName="Language_id"))
private List<Language> languages;

//Setter and Getter
}

MedicalService.class

@Entity
@Table(name = "Medical_Service")
public class MedicalService {

@Id
private int medical_id;

private String medical_name;

private String description;

@ManyToMany(mappedBy="services")
private List<Hospital> hospitals;
//Setter and Getter
}

Language.class

@Entity
@Table(name = "Language")
public class Language {

@Id
private int language_id;

private String language_name;

private String display_name;

@ManyToMany(mappedBy="languages")
private List<Hospital> hospitals;
//Setter and Getter
}

【问题讨论】:

  • 无法告诉您为什么找不到 CLASS 医院的字段“邮政编码”,因为我看不到 CLASS。也许FIELD不叫邮政编码?毕竟 JPQL 使用 CLASSES 和 FIELDS 而不是 TABLES 和 COLUMNS。
  • 上面添加了三个实体
  • 所以没有名为“邮政编码”的字段。有一种叫做“邮编”。名称在 Java 中区分大小写,在 JPQL 中也是如此。你的“加入”也是错误的......你通过关系加入,而不是使用 ON 和列

标签: java mysql spring hibernate jpa


【解决方案1】:

我认为您的查询可能是错误的,这可能是问题的原因。

您目前正在使用:

 SELECT h FROM Hospital h
     INNER JOIN Medical_Service m ON h.hospital_id = m.hospital_id
     WHERE h.Postcode = :postcode AND m.Medical_name = :medical

问题可能是 Medical_Service 不包含 Hospital_id 字段(在 JOIN 中使用)。

如果您乐于使用本机查询,您可以这样做:

 SELECT * FROM Hospital WHERE Postcode = 3000 AND Hospital_id IN
    (SELECT Hospital_id FROM Hospital_Medical hm INNER JOIN Medical_Service m ON hm.Medical_id = m.Medical_id
    where Medical_name = 'Emergency')

内部 SELECT 获取提供紧急服务的医院的所有 Hospital_id。然后,外部选择会选择 Hospital_id 在内部 SELECT 中的所有医院(即它们提供紧急服务),但也只选择邮政编码为 3000 的医院。

要使用本机查询,您需要执行以下操作:

    int postcode = 3000;
    String service = "Emergency";

    StringBuilder sb = new StringBuilder(); 
        sb.append("SELECT * FROM Hospital WHERE Postcode = ");
        sb.append(postcode);
        sb.append("AND Hospital_id IN SELECT Hospital_id FROM Hospital_Medical hm INNER JOIN "
                + "Medical_Service m ON hm.Medical_id = m.Medical_id where Medical_name = '");
        sb.append(service);
        sb.append("')");

    String queryString = sb.toString();
    Query query = em.createNativeQuery(queryString);
    List<Hospital> result = query.getResultList();

【讨论】:

  • 我在上面添加了三个实体。如果我使用本机查询,如何在 sql.xml 中给出参数。而Hospital_Medical是多对多关系的中间表,我还需要添加这个实体吗?
  • @Frank2018 我已经编辑了答案以显示正在构建的查询以及如何传递参数。关于查询Hospital_Medical,您必须使用它,因为该表告诉您哪些医院提供“紧急”服务。
  • 有效!谢谢你的解释!我能再问你一个问题吗?如果我想通过PostcodeMedicalLanguage搜索医院,该如何编写SQL?
  • @Frank2018,当然没问题。请在此处接受此答案,并在单独的问题中提出您的新问题。只是为了保持整洁。
  • 谢谢!这是另一个问题快速链接:stackoverflow.com/questions/36385393/….
猜你喜欢
  • 2016-07-22
  • 1970-01-01
  • 2013-11-18
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多