选择查询的H2数据库问题 - 结果错误

时间:2015-10-24 20:24:35

标签: java mysql sql hibernate h2

我的h2数据库上有一个非常奇怪的行为,在特定的数据库表上有一个简单的选择查询。这个查询在MySQL中工作得很好,但是如果我将我的应用程序的底层数据库切换到H2,它会返回错误的结果(应用程序既可以在MySQL上运行,也可以在H2 DB上运行)。

我有第二个几乎完全相同的查询,工作正常,所以我在这里发布,以便更好地理解。

有两个表:“StudyProtocolNames”和“StudyRfCoils”,它们与表“StudyDetails”具有N-1关系(StudyDetails.stId主键是StudyProtocolNames和StudyRfCoils上的外键)。

这是父表类“StudyDetails”:

@Entity
@Table(name="StudyDetails", 
uniqueConstraints = @UniqueConstraint(columnNames = "StudyInstanceUID"))
public class StudyDetails implements Serializable {  

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name="StId", unique = true, nullable = false)
    private Long stId;

    @Column(name="StudyInstanceUID", unique=true, nullable = false)
    private String studyInstanceUID;

    @Column(name="SoapResponse")
    private int soapResponse;

    @Column(name="PatientName")
    private String patientName;

    @Column(name="RfCoil", nullable = false)
    private String rfCoil;

    @Column(name="ProtocolName", nullable = false)
    private String protocolName;

    ...

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "studyDetails", cascade = CascadeType.ALL)
private Set<StudyProtocolNames> studyProtocolNames = new HashSet<>(0);

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "studyDetails", cascade = CascadeType.ALL)
private Set<StudyRfCoils> studyRfCoils = new HashSet<>(0);
    ...
}

这里是“StudyProtocolNames”和“StudyRfCoils”类:

@Entity 
@Table(name="StudyProtocolNames")
public class StudyProtocolNames implements Serializable {

    private static long serialVersionUID = -298254562330274106L;

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "PnId", unique = true, nullable = false)
    private Long pnId;


    @Column(name="StudyInstanceUID")
    private String studyInstanceUID;

    @Column(name="ProtocolName", nullable = false)
    private String protocolName;

    @ManyToOne
    @JoinColumn(name = "StId", referencedColumnName="StId")
    private StudyDetails studyDetails;
    ...
}

...

@Entity 
@Table(name="StudyRfCoils")
public class StudyRfCoils implements Serializable {

    private static long serialVersionUID = -298254562330274106L;

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "RfcId", unique = true, nullable = false)
    private Long rfcId;

    @Column(name="StudyInstanceUID")
    private String studyInstanceUID;

    @Column(name="RfCoil", nullable = false)
    private String rfCoil;

    @ManyToOne
    @JoinColumn(name = "StId", referencedColumnName="StId")
    private StudyDetails studyDetails;
    ...
}

在我的应用程序的某一点,在将新记录插入“StudyProtocolNames”之前,我检查是否已存在具有相同studyInstanceUID和protocolName的记录。如果已有这样的记录,则此方法返回true。

@Override
public Boolean checkDicomStudyProtocolNameExistForStudy(String studyInstanceUID, String protocolName) {

    Boolean status = false;

    List<String> results=new ArrayList<>();
    Session s=HibernateUtil.openSession();
    s.beginTransaction();
    String hql = "FROM StudyProtocolNames E WHERE E.studyInstanceUID = :studyInstanceUID AND E.protocolName = :protocolName";
    Query query = s.createQuery(hql);
    query.setParameter("protocolName", protocolName.trim());
    query.setParameter("studyInstanceUID", studyInstanceUID);
    results = query.list();
    s.getTransaction().commit();
    s.close();
    log.info(results.size() + " Records found for study in checkDicomStudyProtocolNameExistForStudy: " + studyInstanceUID + " and protocolName" + protocolName);
    if(results.isEmpty()) {
        status = false;
    } else {
        status = true;
    }

    return status;
}

我正在对“StudyRfCoils”表进行完全相同的检查(不同列的逻辑相同):

@Override
public Boolean checkDicomStudyRfCoilExistForStudy(String studyInstanceUID, String rfCoil) {

    Boolean status = false;

    List<String> results=new ArrayList<>();
    Session s=HibernateUtil.openSession();
    s.beginTransaction();
    String hql = "FROM StudyRfCoils E WHERE E.studyInstanceUID = :studyInstanceUID AND E.rfCoil = :rfCoil";
    Query query = s.createQuery(hql);
    query.setParameter("rfCoil", rfCoil.trim());
    query.setParameter("studyInstanceUID", studyInstanceUID);
    results = query.list();
    s.getTransaction().commit();
    s.close();
    log.info(results.size() + " Records found for study in checkDicomStudyRfCoilExistForStudy: " + studyInstanceUID + " and rfCoil: " + rfCoil);
    if(results.isEmpty()) {
        status = false;
    } else {
        status = true;
    }

    return status;

}

表StudyProtocolNames的第一次检查查询工作正常,如果具有相同“studyInstanceUID”和“protocolName”的记录则返回true。

然而,第二个查询总是返回FALSE。它无法找到具有相同“studyInstanceUID”和“rfCoil”的现有记录。所以我在我的数据库表中结束了多个记录,其中列“studyInstanceUID”和“rfCoil”具有相同的值:

enter image description here

另一个奇怪的事实是,当我切换到MySQL时,第二次检查查询工作FINE。只有在使用H2 DB时才会发生这种奇怪的行为。

1 个答案:

答案 0 :(得分:0)

似乎这种行为是由我执行rfCoil字符串值的trim()引起的:

@Override
public Boolean checkDicomStudyRfCoilExistForStudy(String studyInstanceUID, String rfCoil) {
    ...
    query.setParameter("rfCoil", rfCoil.trim());
    ...

但是在MySQL中没有发生这种情况