嵌入式id成员成员值的Hibernate标准

时间:2014-08-01 17:45:59

标签: java hibernate criteria

我想找一个使用critera的实体,它限制第二个实体的属性值,该实体是我第一个实体的嵌入式id的成员。

第一个实体:

@Entity
public class Car {

    @EmbeddedId
    private Id id = new Id();

    private String color;

    @Embeddable
    public static class Id implements Serializable {

        private static final long serialVersionUID = -8141132005371636607L;

        @ManyToOne
        private Owner owner;

        private String model;

        // getters and setters...
        // equals and hashcode methods

    }

    // getters and setters...

}

第二实体:

@Entity
public class Owner {

    @Id
    @GeneratedValue (strategy = GenerationType.AUTO)
    private Long id;
    private String firstname;    
    private String lastname;

    @OneToMany (mappedBy = "id.owner")
    private List<Car> cars;

    // getters and setters...

}

在这个例子中,我想获得一辆颜色为“黑色&#39;”型号&#39; batmobile&#39;和老板的名字&#39;布鲁斯&#39; (哎呀......剧透;))

我尝试做类似的事情,但它没有工作:

List<Car> cars = session.createCriteria(Car.class)
      .add(Restrictions.eq("color", "black"))
      .add(Restrictions.eq("id.model", "batmobile"))
      .createAlias("id.owner", "o")
      .add(Restrictions.eq("o.firstname", "Bruce"))
      .list();

结果:

Hibernate: select this_.model as model1_0_0_, this_.owner_id as owner_id3_0_0_, this_.color as color2_0_0_ from Car this_ where this_.color=? and this_.model=? and o1_.firstname=?
ERROR: Unknown column 'o1_.firstname' in 'where clause'

获得我想要的东西的正确方法是什么?

更新

我试过hql:

String hql = "FROM Car as car where car.color = :color and car.id.model = :model and car.id.owner.firstname = :firstname";

Query query = em.createQuery(hql);
query.setParameter("color", "black");
query.setParameter("model", "batmobile");
query.setParameter("firstname", "Bruce");

List<Car> cars = query.getResultList();

它有效,但有没有办法用标准来做到这一点?

2 个答案:

答案 0 :(得分:0)

您忘记在firstname和lastname字段(以及Car中的颜色字段)之上添加@Column注释。在休眠状态下,如果未注释某个字段,则不会将其识别为数据库字段。 This page should give you a good idea about how to set up your model objects

注意:您可以在getter上使用列注释并且没问题,但是您没有显示getter。这两个地方都没问题。


看看HQL正在吐出的内容,特别是声明(为便于阅读而编写):

select 
    this_.model as model1_0_0_, 
    this_.owner_id as owner_id3_0_0_, 
    this_.color as color2_0_0_ 
from Car this_ 
where 
    this_.color=? 
    and this_.model=? 
    and o1_.firstname=?

看起来hibernate正在将字段“id.owner”翻译为“o”,因为你的别名告诉它,但由于某种原因,它并没有按照预期写下“id.owner = o”。您可能想要研究它为什么这样做。

答案 1 :(得分:0)

根据https://hibernate.atlassian.net/browse/HHH-4591,有一种解决方法。

您必须将@EmbeddedId(在这种情况下为owner)所需的关系属性复制到主要实体(在本例中为Car)并insertable = false, updatable = false为如下

@Entity
public class Car {

    @EmbeddedId
    private Id id = new Id();

    private String color;

    @ManyToOne
    @JoinColumn(name = "column_name", insertable = false, updatable = false)
    private Owner owner;

    @Embeddable
    public static class Id implements Serializable {

        private static final long serialVersionUID = -8141132005371636607L;

        @ManyToOne
        private Owner owner;

        private String model;

        // getters and setters...
        // equals and hashcode methods

    }

    // getters and setters...

}

然后直接创建别名而不是使用复合id属性

List<Car> cars = session.createCriteria(Car.class)
      .add(Restrictions.eq("color", "black"))
      .add(Restrictions.eq("id.model", "batmobile"))

      .createAlias("owner", "o")

      .add(Restrictions.eq("o.firstname", "Bruce"))
      .list();