简体   繁体   中英

Hibernate, OneToMany association - select issue

I have following entity classes: User and Category. User might have multiple categories. I need to compose a query to select a user with some specific email and fetch categories, which updated value is greater than specified by me.

Unfortunately, I get some weird ( from my point of view ) errors. Here is a query:

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;

I've also tried this query:

String selectQuery = "from User as user left outer join user.categories as category where category.updated >= :after and user.email = :email";

I get an error message:

java.lang.ClassCastException: Category cannot be cast to User

Does anybody have any clue? The error message seems weird to me, cause I am selecting from User, not from Category. PS Of course, query should work if user doesn't have any categories at all.

Here are the entities:

@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;
    }
}

Thank you in advance. Any help would be highly appreciated.

The "FETCH" option will always retrieve all categories for an user and you'd have to filter it in 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

The categories can't be filtered with this query, since the left join fetch doesn't allow you to use the alias in a where clause.

For a more efficient query you would need to let go the "FETCH" and this way you can filter the categories too, but this time you won't be able to retrieve an user with a "partial" view of his categories. You either fetch all children or none.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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