Java Hibernate,OneToMany关联-选择问题

Java Hibernate,OneToMany关联-选择问题,java,hibernate,jpa,orm,one-to-many,Java,Hibernate,Jpa,Orm,One To Many,我有以下实体类: 用户和类别。用户可能有多个类别。 我需要编写一个查询来选择具有特定电子邮件和获取类别的用户,更新后的值大于我指定的值 不幸的是,我(在我看来)犯了一些奇怪的错误。 以下是一个问题: String selectQuery = "from User as user left outer join user.categories as category with category.updated >= :after where user.email = :email"; Use

我有以下实体类: 用户和类别。用户可能有多个类别。 我需要编写一个查询来选择具有特定电子邮件和获取类别的用户,更新后的值大于我指定的值

不幸的是,我(在我看来)犯了一些奇怪的错误。 以下是一个问题:

String selectQuery = "from User as user left outer join user.categories as category with category.updated >= :after where user.email = :email";
User u = (User)sessionFactory.getCurrentSession().createQuery(selectQuery).
            setString("email", email).
            setCalendar("after", after).
            setResultTransformer(RootEntityResultTransformer.INSTANCE).
            uniqueResult();
return u;
我还尝试了以下查询:

String selectQuery = "from User as user left outer join user.categories as category where category.updated >= :after and user.email = :email";
我收到一条错误消息:

java.lang.ClassCastException: Category cannot be cast to User
有人有什么线索吗?这个错误消息对我来说似乎很奇怪,因为我是从用户而不是类别中选择的。 当然,若用户根本并没有任何类别,那个么查询应该可以工作

以下是实体:

@Entity
@Table(name = "USER", uniqueConstraints = {
        @UniqueConstraint(columnNames = {"EMAIL"})
})
public class User extends AbstractTimestampEntity implements Serializable {

    public User() {

    }

    private Integer id;

    private String email;

    private Set<Category> categories = null;

    @Id
    @Column(name = "ID")
    @GeneratedValue
    public Integer getId() {
        return id;
    }

    @NotEmpty
    @Email
    @Column(name = "EMAIL")
    public String getEmail() {
        return email;
    }

    @Cascade( { org.hibernate.annotations.CascadeType.PERSIST } )
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
    public Set<Category> getCategories() {
        return categories;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setCategories(Set<Category> categories) {
        this.categories = categories;
    }
}


@Entity
@Table(name = "CATEGORY")
public class Category extends AbstractTimestampEntity implements Serializable {

    private Integer id;

    private User user;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", unique = true, nullable = false)
    public Integer getId() {
        return id;
    }

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "USER_ID")
    public User getUser() {
        return user;
    }


   public void setId(Integer id) {
        this.id = id;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

@MappedSuperclass
public class AbstractTimestampEntity {

    private Calendar created;

    private Calendar updated;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATED")
    public Calendar getCreated() {
        return created;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "UPDATED")
    public Calendar getUpdated() {
        return updated;
    }

    public void setCreated(Calendar created) {
        this.created = created;
    }

    public void setUpdated(Calendar updated) {
        this.updated = updated;
    }
}
@实体
@表(name=“USER”,唯一约束={
@UniqueConstraint(columnNames={“EMAIL”})
})
公共类用户扩展AbstractTimestampEntity实现可序列化{
公共用户(){
}
私有整数id;
私人字符串电子邮件;
私有集合类别=null;
@身份证
@列(name=“ID”)
@生成值
公共整数getId(){
返回id;
}
@空空如也
@电子邮件
@列(name=“EMAIL”)
公共字符串getEmail(){
回复邮件;
}
@级联({org.hibernate.annotations.CascadeType.PERSIST})
@OneToMany(fetch=FetchType.LAZY,mappedBy=“user”)
公共集合getCategories(){
退货类别;
}
公共无效集合id(整数id){
this.id=id;
}
公用电子邮件(字符串电子邮件){
this.email=电子邮件;
}
公共无效集合类别(集合类别){
这个。类别=类别;
}
}
@实体
@表(name=“CATEGORY”)
公共类类别扩展AbstractTimestampEntity实现可序列化{
私有整数id;
私人用户;
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“ID”,unique=true,nullable=false)
公共整数getId(){
返回id;
}
@NotNull
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“USER\u ID”)
公共用户getUser(){
返回用户;
}
公共无效集合id(整数id){
this.id=id;
}
公共void setUser(用户){
this.user=用户;
}
}
@映射超类
公共类抽象实体{
创建私人日历;
更新私人日历;
@时态(TemporalType.TIMESTAMP)
@列(name=“CREATED”)
公共日历getCreated(){
创建回报;
}
@时态(TemporalType.TIMESTAMP)
@列(name=“UPDATED”)
公共日历getUpdated(){
更新的回报;
}
已创建公共作废集(已创建日历){
this.created=created;
}
公共作废设置日期(日历更新){
this.updated=已更新;
}
}
先谢谢你。 非常感谢您的帮助。

FETCH选项将始终为用户检索所有类别,您必须用Java对其进行筛选:

String selectQuery = 
            "from User as user " +
            "left join fetch user.categories as category " +
            "where " +
            "   user.email = :email";
User user = (User) session.createQuery(selectQuery).
        setString("email", email).
        uniqueResult();
return user;
//then filter the user.categories by the after criteria
无法使用此查询筛选类别,因为左侧联接获取不允许在where子句中使用别名

为了获得更高效的查询,您需要放弃“FETCH”,这样您也可以过滤类别,但这一次您将无法检索具有“部分”类别视图的用户。你要么得到所有的孩子,要么一个也没有

String selectQuery = 
            "select user, category " +
            "from User as user " +
            "left join user.categories as category with category.updated >= :after " +
            "where " +
            "   user.email = :email";
List userAndCategories = session.createQuery(selectQuery).
        setString("email", email).
        setCalendar("after", after).
        list();     
//userAndCategories contains Object[] entries where the User is the Object[0] is the user and Object[1] is the Category

显示对象的代码可能会有所帮助……请发布
User
Category
类,好了。感谢您对我的问题感兴趣。从用户中选择用户作为用户左侧外部加入获取用户。类别作为类别其中category.updated>=:after和user.email=:email此查询通过了所有单元测试,只有一个例外:当用户没有任何与他相关联的类别时。感谢您的回复。我将在我的代码中尝试。不客气。检查这两种方法,看看哪一种更适合您当前的问题环境。前者更容易集成,而后者应该表现得更好。