【问题标题】:Hibernate: Using native SQL + addEntity()Hibernate:使用原生 SQL + addEntity()
【发布时间】:2016-10-13 06:52:41
【问题描述】:

我有表A,它与表B 有关系,为一对多。 我想要做的是从表A 和加入选定的结果表B 中使用іщьу 限制进行选择。 所以我遇到了一个问题,如何以正确的方式在休眠中做到这一点?

典型的Criteria.selectMaxResults 这不是我需要的,因为限制将在加入后接受,而不是从表A 中获取 10 个不同的行,例如,我会从表“A”中得到 1 行,加入 10表B 中的不同行。

(1) 那么最好的方法是什么?在一个查询中从A 中仅选择唯一行,在另一个查询中使用连接BA 中选择?

一般来说,在原生 SQL 语言上,我希望执行下一个查询:

String sQuery = SELECT a.*,b* FROM (SELECT * FROM parentTable WHERE c.id=777 LIMIT 0,10) AS a, b.* WHERE a.id=b.a_id;

因此,根据休眠教程和文档,我尝试使用session.createSQLQuery(sQuery)。我的方法看起来是这样的:

@Override
@Transactional
public List<VocabularyWord> getWords(int vocId, int firstResult, int pageSize) {
    Session s = this.template.getSessionFactory().getCurrentSession();
    SQLQuery query = s.createSQLQuery("SELECT {vW.*}, m.* FROM (SELECT * FROM vocabulary_words AS vw WHERE vw.vocabulary_id=:id LIMIT :from,:size) AS vW, meaning AS m WHERE vW.id=m.vocabulary_words_id;");
    query.setInteger("id", vocId);
    query.setInteger("from", firstResult);
    query.setInteger("size", pageSize);
    query.addEntity("vW", VocabularyWord.class);
    query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    //  If unccoment the next word I get error: Column 'id1_1_1_' not found. But as I'have understood I don't need this.
    //    query.addEntity("m", Meaning.class);
    List l = query.list();
    return l;
} 

这个方法返回的正是我想要的。但是要返回此结果,休眠会执行大量查询。 (他尝试做类似(1)的事情?)。恰好Hibernate 执行 5 个下一个查询

Hibernate: 
    SELECT
        vW.id as id1_7_0_,
        vW.original_text as original2_7_0_,
        vW.transcription as transcri3_7_0_,
        vW.vocabulary_id as vocabula4_7_0_,
        m.* 
    FROM
        (SELECT
            * 
        FROM
            vocabulary_words AS vw 
        WHERE
            vw.vocabulary_id=? LIMIT ?,?) AS vW,
        meaning AS m 
    WHERE
        vW.id=m.vocabulary_words_id;
Hibernate: 
    select
        meaning0_.vocabulary_words_id as vocabula5_1_0_,
        meaning0_.id as id1_1_0_,
        meaning0_.id as id1_1_1_,
        meaning0_.definition as definiti2_1_1_,
        meaning0_.example as example3_1_1_,
        meaning0_.translation as translat4_1_1_,
        meaning0_.vocabulary_words_id as vocabula5_1_1_,
        meaning0_.w_type as w_type6_1_1_ 
    from
        meaning meaning0_ 
    where
        meaning0_.vocabulary_words_id=?
Hibernate: 
    select
        meaning0_.vocabulary_words_id as vocabula5_1_0_,
        meaning0_.id as id1_1_0_,
        meaning0_.id as id1_1_1_,
        meaning0_.definition as definiti2_1_1_,
        meaning0_.example as example3_1_1_,
        meaning0_.translation as translat4_1_1_,
        meaning0_.vocabulary_words_id as vocabula5_1_1_,
        meaning0_.w_type as w_type6_1_1_ 
    from
        meaning meaning0_ 
    where
        meaning0_.vocabulary_words_id=?
Hibernate: 
    select
        meaning0_.vocabulary_words_id as vocabula5_1_0_,
        meaning0_.id as id1_1_0_,
        meaning0_.id as id1_1_1_,
        meaning0_.definition as definiti2_1_1_,
        meaning0_.example as example3_1_1_,
        meaning0_.translation as translat4_1_1_,
        meaning0_.vocabulary_words_id as vocabula5_1_1_,
        meaning0_.w_type as w_type6_1_1_ 
    from
        meaning meaning0_ 
    where
        meaning0_.vocabulary_words_id=?
Hibernate: 
    select
        meaning0_.vocabulary_words_id as vocabula5_1_0_,
        meaning0_.id as id1_1_0_,
        meaning0_.id as id1_1_1_,
        meaning0_.definition as definiti2_1_1_,
        meaning0_.example as example3_1_1_,
        meaning0_.translation as translat4_1_1_,
        meaning0_.vocabulary_words_id as vocabula5_1_1_,
        meaning0_.w_type as w_type6_1_1_ 
    from
        meaning meaning0_ 
    where
        meaning0_.vocabulary_words_id=?

我的VocabularyWord 实体

public class VocabularyWord implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", updatable = false, nullable = false)
    private int id;
    @Column(name = "vocabulary_id", updatable = false, nullable = false)
    private int vocId;
    @Column(name = "original_text", nullable = false)
    private String originalText;
    @Column(name="transcription", nullable = true)
    private String transcription;
    @OneToMany (mappedBy = "vocWord", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Meaning> meaning;

    // + getters and setters
}

我的意义实体

public class Meaning implements Serializable {
    @Id
    @Column(name = "id", updatable = false, nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "vocabulary_words_id", nullable = false, updatable = false)
    private VocabularyWord vocWord;
    @JsonIgnore
    @Column(name = "vocabulary_words_id", updatable = false, insertable = false)
    private int vocWordId;
    @Column(name = "w_type", nullable = true, unique = false)
    private String wType;
    @Column(name = "example", nullable = true, unique = false)
    private String example;
    @Column(name = "definition", nullable = true, unique = false)
    private String definition;
    @Column(name = "translation", nullable = true, unique = false)
    private String translation;
    //+ getters and setters
}

我该如何解决这个问题?或者,我是否选择了其他方式来实现该查询?

我将不胜感激任何帮助、建议、想法和相关链接。提前致谢。

【问题讨论】:

    标签: java mysql spring hibernate


    【解决方案1】:

    我已通过更改查询并添加.addJoin().addRootEntity() 解决了我的问题。所以现在我的方法 getWords 看起来接下来:

    @Override
    @Transactional
    public List<VocabularyWord> getWords(int vocId, int firstResult, int pageSize) {
    Session s = this.template.getSessionFactory().getCurrentSession();
    SQLQuery query = s.createSQLQuery("SELECT {vW.*}, {m.*} FROM (SELECT * FROM vocabulary_words AS vw WHERE vw.vocabulary_id=:id LIMIT :from,:size) AS vW LEFT JOIN meaning AS m ON (m.vocabulary_words_id = vW.id);");
    query.addEntity("vW", VocabularyWord.class)
    .addJoin("m", "vW.meaning")
    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
    .setInteger("id", vocId)
    .setInteger("from", firstResult)
    .setInteger("size", pageSize);
    query.addRoot("vW", VocabularyWord.class);
    List l = query.list();
    return l;
    }
    

    这个方法只执行一个查询:

    Hibernate: 
        SELECT
            vW.id as id1_7_0_,
            vW.original_text as original2_7_0_,
            vW.transcription as transcri3_7_0_,
            vW.vocabulary_id as vocabula4_7_0_,
            m.vocabulary_words_id as vocabula6_1_0__,
            m.id as id1_1_0__,
            m.id as id1_1_1_,
            m.definition as definiti2_1_1_,
            m.example as example3_1_1_,
            m.translation as translat4_1_1_,
            m.vocabulary_words_id as vocabula6_1_1_,
            m.w_type as w_type5_1_1_ 
        FROM
            (SELECT
                * 
            FROM
                vocabulary_words AS vw 
            WHERE
                vw.vocabulary_id=? LIMIT ?,?) AS vW 
        LEFT JOIN
            meaning AS m 
                ON (
                    m.vocabulary_words_id = vW.id
                );
    

    【讨论】:

      猜你喜欢
      • 2017-06-01
      • 2014-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 2011-08-28
      • 1970-01-01
      • 2012-10-09
      相关资源
      最近更新 更多