如何使用Hibernate标准从连接表中选择特定实体?

时间:2016-03-31 09:13:04

标签: java hibernate hibernate-criteria

我有这个SQL语句:

 select c.*
 from tableA a
 inner join tableB b on a.id = b.a_id                            
 inner join tableC c on b.id = c.b_id

我的标准是:

Criteria criteria = session.createCriteria(tableA.class, "a")
                .createAlias("a.b", "b")
                .createAlias("b.c", "c");

如何选择符合条件的tableC?

之类的东西 -

List<tableC> listC = criteria.list()

我尝试添加投影.setProjection(Property.forName("c"))

但是我收到了以下错误:

org.hibernate.QueryException: could not resolve property: c of: ...xx.xx.tableA
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:81)
at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:75)
at org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1465)

这是我的课程:

CnTermsGroup类

@Entity
@Table(name="CN_TERMS_GROUP")
public class CnTermsGroup extends implements Serializable {

private static final long serialVersionUID = 1145853863134597537L;

@Id 
@Column(name="CN_TERMS_GROUP_ID")
private long cnTermsGroupId;

@Column(name="CN_TERMS_GROUP_NAME")
private String cnTermsGroupName;

@OneToMany(mappedBy="cnTermsGroup", cascade=CascadeType.ALL, orphanRemoval=true)
@Fetch(FetchMode.SUBSELECT)
private List<CnTermsCounted> cnTermsCounteds;

public CnTermsGroup() { 
}

public long getCnTermsGroupId() {
    return this.cnTermsGroupId;
}

public void setCnTermsGroupId(long cnTermsGroupId) {
    this.cnTermsGroupId = cnTermsGroupId;
}

public String getCnTermsGroupName() {
    return this.cnTermsGroupName;
}

public void setCnTermsGroupName(String cnTermsGroupName) {
    this.cnTermsGroupName = cnTermsGroupName == null ? "" : cnTermsGroupName;
}

public List<CnTermsCounted> getCnTermsCounteds() {
    return this.cnTermsCounteds;
}

public void setCnTermsCounteds(List<CnTermsCounted> cnTermsCounteds) {
    this.cnTermsCounteds = cnTermsCounteds;
}

@Override
public Object getId(){
    return cnTermsGroupId;
}

}

CnTermsCounted类

@Entity
@Table(name="CN_TERMS_COUNTED")
public class CnTermsCounted extends BaseModelImp  implements Serializable{

private static final long serialVersionUID = -8486592249097766983L;

@Id 
@Column(name="CN_TERMS_COUNTED_ID")
private long cnTermsCountedId;

@ManyToOne(fetch = FetchType.LAZY)
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
@JoinColumn(name="CN_TERMS_GROUP_ID")
private CnTermsGroup cnTermsGroup;

@OneToMany(mappedBy = "cnTermsCounted", cascade=CascadeType.ALL, orphanRemoval=true)
@Fetch(FetchMode.SUBSELECT)
private Set<CnTermsRun> cnTermsRuns;

public CnTermsCounted() {
}

public long getCnTermsCountedId() {
    return this.cnTermsCountedId;
}

public void setCnTermsCountedId(long cnTermsCountedId) {
    this.cnTermsCountedId = cnTermsCountedId;
}

public CnTermsGroup getCnTermsGroup() {
    return this.cnTermsGroup;
}

public void setCnTermsGroup(CnTermsGroup cnTermsGroup) {
    this.cnTermsGroup = cnTermsGroup;
}


public Set<CnTermsRun> getCnTermsRuns() {
    return this.cnTermsRuns;
}

public void setCnTermsRuns(Set<CnTermsRun> cnTermsRuns) {
    this.cnTermsRuns = cnTermsRuns;
}

@Override
public Object getId() {
    return cnTermsCountedId;
}

}

和CnTermsRun类

@Entity
@Table(name="CN_TERMS_RUN")
public class CnTermsRun extends BaseModelImp {
private static final long serialVersionUID = -9042920700902106238L;

@Id
@Column(name="CN_TERMS_RUN_ID")
private long cnTermsRunId;

@ManyToOne
@JoinColumn(name="CN_TERMS_COUNTED_ID")
private CnTermsCounted cnTermsCounted;


public CnTermsRun() {
}

public long getCnTermsRunId() {
    return this.cnTermsRunId;
}

public void setCnTermsRunId(long cnTermsRunId) {
    this.cnTermsRunId = cnTermsRunId;
}


public CnTermsCounted getCnTermsCounted() {
    return this.cnTermsCounted;
}

public void setCnTermsCounted(CnTermsCounted cnTermsCounted) {
    this.cnTermsCounted = cnTermsCounted;
}

/* (non-Javadoc)
 * @see com.sintecmedia.onair.model.imp.BaseModelImp#getId()
 */
@Override
public Object getId() {
    return cnTermsRunId;
}
}

和标准:

Criteria criteria = session.createCriteria(CnTermsGroup.class, "cnTermsGroup")
        .createAlias("cnTermsGroup.cnTermsCounteds", "cnTermsCounted")
        .createCriteria("cnTermsCounted.cnTermsRuns")
        .setResultTransformer(Transformers.aliasToBean(CnTermsRun.class));

1 个答案:

答案 0 :(得分:1)

我可以想到两种方法。

第一种方法是使用Criteria.ALIAS_TO_ENTITY_MAP,如下所示

Criteria criteria = session.createCriteria(CnTermsGroup.class, "cnTermsGroup")
        .createAlias("cnTermsGroup.cnTermsCounteds", "cnTermsCounted")
        .createAlias("cnTermsCounted.cnTermsRuns", "cnTermsRuns")
        .setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);

这会返回List<Map<String, Object>>。我们可以使用alias name收集所需的实体,如下所示,例如:收集CnTermsRun个实体:

List<CnTermsRun> subEntities = new ArrayList<>();
List<Map<String, Object>> objects = criteria.list();
for (Map<String, Object> record : objects) {
    subEntities.add((CnTermsRun)record.get("cnTermsRuns"));
}

第二种方法是使用Transformers.aliasToBean(...),如下所示

这会直接返回List<CnTermsRun>,但需要添加新的constructor以及默认构造函数:

public CnTermsRun(long cnTermsRunId, CnTermsCounted cnTermsCounted) {
    this.cnTermsRunId = cnTermsRunId;
    this.cnTermsCounted = cnTermsCounted;
}

以下标准:

Criteria criteria = session.createCriteria(CnTermsGroup.class, "cnTermsGroup")
        .createAlias("cnTermsGroup.cnTermsCounteds", "cnTermsCounted")
        .createAlias("cnTermsCounted.cnTermsRuns", "cnTermsRuns")
        .setProjection(Projections.projectionList().add(Projections.alias(Projections.property("cnTermsRuns.id"), "cnTermsRunId")).add(Projections.alias(Projections.property("cnTermsRuns.cnTermsCounted"), "cnTermsCounted")))
        .setResultTransformer(Transformers.aliasToBean(CnTermsRun.class));
List<CnTermsRun> subEntities = criteria.list();