简体   繁体   English

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

[英]Hibernate criteria on embedded id member member value

I would like to find an entity using a critera with restriction on the value of an attribute of a second entity wich is a member of the embedded id of my first entity. 我想找一个实体使用一个限制第二个实体的属性值的critera,它是我第一个实体的嵌入式id的成员。

First entity : 第一实体:

@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...

}

Second entity : 第二实体:

@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...

}

In this example, I would like to obtain the car with the color 'black', model 'batmobile' and the owner's firstname 'Bruce' (oops... spoiler ;) ) 在这个例子中,我想获得颜色为“黑色”的车型,型号为“batmobile”,车主的名字为“Bruce”(oops ...剧透;))

I tried to do something like that but it won't work : 我尝试做类似的事情,但它不会起作用:

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();

Result : 结果:

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'

What is the right way to obtain what I want ? 什么是获得我想要的正确方法?

update 更新

I tried in hql : 我在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();

It works but is there a way to do this with criteria ? 它有效但是有没有办法用标准来做到这一点?

You forgot to add the @Column annotation on top of the firstname and lastname fields (and the color field in Car). 您忘记在名字和姓氏字段(以及Car中的颜色字段)之上添加@Column注释。 In hibernate if a field is not annotated, it doesn't recognize it as a database field. 在休眠状态下,如果未注释某个字段,则不会将其识别为数据库字段。 This page should give you a good idea about how to set up your model objects . 此页面可以让您了解如何设置模型对象

NOTE: You can have the column annotation over the getters and be fine, but you didn't show the getters. 注意:您可以将列注释放在getter上并且没问题,但是您没有显示getter。 Either place is fine. 这两个地方都没关系。


Look at what HQL is spitting back out, specifically the statement (formated for easier reading): 看看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=?

It looks like hibernate is translating the field "id.owner" to "o" as your alias told it to to, but for some reason it's not writing down that "id.owner=o" as intended. 看起来hibernate正在将字段“id.owner”翻译为“o”,因为你的别名告诉它,但由于某种原因,它并没有按照预期写下“id.owner = o”。 You may want to do some research into why it may be doing that. 您可能想要研究它为什么这样做。

As per https://hibernate.atlassian.net/browse/HHH-4591 there is a workaround. 根据https://hibernate.atlassian.net/browse/HHH-4591,有一种解决方法。

You have to copy the needed relation-property of the @EmbeddedId ( owner in this case) to the main entity ( Car in this case) with insertable = false, updatable = false as follows 您必须将@EmbeddedId (在本例中为owner )所需的relation-property复制到主实体(在本例中为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...

}

Then just create directly the alias instead of using the composite id property 然后直接创建别名而不是使用复合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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM