Java 如何使用hibernate查询具有嵌套对象集合的嵌套对象

Java 如何使用hibernate查询具有嵌套对象集合的嵌套对象,java,hibernate,Java,Hibernate,使用Hibernate,我需要在MySQL数据库中查询Post实体,该Post实体与轮询实体具有一对一的关系,轮询实体与应答实体具有一对多的关系。我需要Post对象包含Poll对象,它的Poll对象包含Answer对象。下面是基本的类设置: 更新: Post表不能有主键列。这是对数据的浪费。我需要能够使用user\u id列从数据库中获取Post对象。使用user_id列获取Post对象是唯一的方法,所以对我来说没有主键列是没有意义的。因此,如果您要提供一个能够深入了解解决我的问题的解决方案的答

使用Hibernate,我需要在MySQL数据库中查询Post实体,该Post实体与轮询实体具有一对一的关系,轮询实体与应答实体具有一对多的关系。我需要Post对象包含Poll对象,它的Poll对象包含Answer对象。下面是基本的类设置:

更新: Post表不能有主键列。这是对数据的浪费。我需要能够使用user\u id列从数据库中获取Post对象。使用user_id列获取Post对象是唯一的方法,所以对我来说没有主键列是没有意义的。因此,如果您要提供一个能够深入了解解决我的问题的解决方案的答案,请记住这些规范

邮班:

@Entity
@Table(name="user_feed")
public class Post implements Serializable {
    //id for the user that is meant to receive the post
    //*post object is taken from a table that will contain
    //*posts for many different users
    @Id
    @Column(name="user_id")
    private long mUserId;

    //poll id
    @Id
    @Column(name="poll_id")
    private long mPollId;

    //boolean that indicates whether this post is a repost
    @Column(name="is_repost")
    private boolean mIsRepost;

    //date the post was created
    @Column(name="date_created")
    private Date mDateCreated;

    //the poll this post contains
    @OneToOne
    @JoinColumn(name="poll_id")
    private Poll mPoll;
@Entity
@Table(name="user_feed")
public class Post implements Serializable {
    @Id
    @Column(name="user_id")
    private long mUserId;

    //removed long mPollId
    //hibernate is capable of getting the foreign key for a post's
    //poll_id column from its poll object -- mPoll
    //so i don't have to have a separate field for the id of this post's
    //poll

    @Column(name="is_repost")
    private boolean mIsRepost;

    @Column(name="date_created")
    private Date mDateCreated;

    //made this field part of the composite id instead of long mPollId
    //pretty much the same composite key as before just had to alter
    //my implementation of Post.equals(Object) to use this poll's id
    //instead of this class's mPollId field
    //implementing your own .equals(Object) method is necessary when
    //creating composite keys as i do with multiple @Id annotations
    //i think you also have to implement your own .hashCode() method too
    //but the word hash scares me, so I didn't do it
    //the code works, so i'm just gonna let it rock
    @OneToOne
    @JoinColumn(name="poll_id")
    private Poll mPoll;
投票类别:

@Entity
@Table(name="poll")
public class Poll implements Serializable{

    //the poll's id
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private long mId;

    //id of the user who created the poll
    @Column(name="user_id")
    private long mUserId;

    //the text of the poll's question
    @Column(name="question")
    private String mQuestion;

    //the date the poll was created
    @Column(name="date_created")
    private Date mDateCreated;

    //the answer objects for this poll
    @OneToMany
    @JoinColumn(name="id")
    private List<Answer> mAnswers;
@Entity
@Table(name="poll")
public class Poll implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private long mId;

    @Column(name="user_id")
    private long mUserId;

    @Column(name="question")
    private String mQuestion;

    @Column(name="date_created")
    private Date mDateCreated;

    //removed @JoinColumn -- not completely sure about why it wasn't
    //helping, but many of the examples similar to my use case didn't
    //use it so I got rid of it
    //added mappedBy variable -- still not really sure what it does
    //but it works
    //and added FetchType.EAGER so everytime a Poll object is loaded
    //the answers it's associated with are loaded too
    @OneToMany(mappedBy="mPoll", fetch=FetchType.EAGER)
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.REMOVE})
    private List<Answer> mAnswers;
***我对这张桌子的id感到困惑。每个答案都有一个主键是没有意义的,但是Hibernate在类中需要某种@Id注释,所以为了Hibernate,我决定在表中创建一个主键列。从来没用过。我想去掉它,但是对于同一个投票来说,除了目前的文本之外,实际上没有任何东西可以使一个答案与另一个答案不同——这对于应用程序逻辑来说是不必要的

我提出的问题:不起作用

这个查询实际上只是我在测试是否可以得到一个包含所有嵌套对象的Post对象。我知道如果我能得到一个,得到一个集合将不会有太多的拉伸-但我甚至不能得到一个

Session session = HibernateUtilities.openSession();
        session.beginTransaction();

        //29 is a post meant for a particular user and 47 is the id of the    
        //poll that should be contained in the post
        Post post = (Post)session.get(Post.class, new Post(29, 47));

        session.getTransaction().commit();
        session.close();

        //suppose to return the post in JSON format to a client, but it
        //doesn't work when I create the one-to-many relationship between       
        //the poll and it's answers. It only works without the relationship;   
        //which I've defined in the Poll class
        return mGson.toJson(post);

您不应该将关系的主键作为它们自己的字段(例如,您不需要Post.mPoll和Post.mPollId,如果需要,只需使用Post.mPoll.getId()。如果我要解决您的问题,默认情况下我会(稍后我们可以讨论Post没有id)使用以下对象模型(为简洁起见省略getter,但我会在所有字段上使用它们)

@实体
公营职位{
@身份证
@生成值
私人长id;
@奥内托内
私人投票;
}
@实体
公众阶级投票{
@身份证
@生成值
私人长id;
@独身癖
私人名单答案;
}
@实体
公开课答案{
@身份证
@生成值
私人长id;
}
从那里开始,看看它在哪里分崩离析。如果希望实体没有任何ID,则可以使用@Embedded、@Embeddeble和@ElementCollection注释

@Embeddeble最初用于嵌入“值”对象(例如货币、日期、邮政地址等),因此这些对象不需要主键,完全由其所属实体所有

您使用@Embedded注释引用可嵌入对象(例如,如果@Embedded post是一对一的,则您的用户将拥有对@Embedded post的@Embedded引用)

要引用可嵌入对象的集合,请使用@ElementCollection注释。但是,@ElementCollection的成员是不可变的(不能在数据库中修改它们,必须将其从集合中删除并添加新实例),并且不能延迟加载。鉴于您的Post对象的复杂性,我个人不会将其作为嵌入式类(您可能希望有一天能够编辑Post?),但如果您希望,它应该可以工作


我之所以说应该,是因为我从来没有一个可嵌入类引用其他不可嵌入的实体(例如,您对Poll的引用)。尝试一下这些方法,如果它们不起作用,请准确地发布出问题所在。

您不应该将关系的主键作为它们自己的字段(例如,您不需要post.mPoll和post.mPollId,如果需要,只需使用post.mPoll.getId()。如果我要解决您的问题,默认情况下我会(稍后我们可以讨论Post没有id)使用以下对象模型(为简洁起见省略getter,但我会在所有字段上使用它们)

@实体
公营职位{
@身份证
@生成值
私人长id;
@奥内托内
私人投票;
}
@实体
公众阶级投票{
@身份证
@生成值
私人长id;
@独身癖
私人名单答案;
}
@实体
公开课答案{
@身份证
@生成值
私人长id;
}
从那里开始,看看它在哪里分崩离析。如果希望实体没有任何ID,则可以使用@Embedded、@Embeddeble和@ElementCollection注释

@Embeddeble最初用于嵌入“值”对象(例如货币、日期、邮政地址等),因此这些对象不需要主键,完全由其所属实体所有

您使用@Embedded注释引用可嵌入对象(例如,如果@Embedded post是一对一的,则您的用户将拥有对@Embedded post的@Embedded引用)

要引用可嵌入对象的集合,请使用@ElementCollection注释。但是,@ElementCollection的成员是不可变的(不能在数据库中修改它们,必须将其从集合中删除并添加新实例),并且不能延迟加载。鉴于您的Post对象的复杂性,我个人不会将其作为嵌入式类(您可能希望有一天能够编辑Post?),但如果您希望,它应该可以工作


我之所以说应该,是因为我从来没有一个可嵌入类引用其他不可嵌入的实体(例如,您对Poll的引用)。尝试一下这些方法,如果它们不起作用,请准确地公布出问题所在。

我自己解决了。下面代码中的所有注释指定了我对问题中提出的代码所做的更改,并解释了我为什么进行这些更改

邮班:

@Entity
@Table(name="user_feed")
public class Post implements Serializable {
    //id for the user that is meant to receive the post
    //*post object is taken from a table that will contain
    //*posts for many different users
    @Id
    @Column(name="user_id")
    private long mUserId;

    //poll id
    @Id
    @Column(name="poll_id")
    private long mPollId;

    //boolean that indicates whether this post is a repost
    @Column(name="is_repost")
    private boolean mIsRepost;

    //date the post was created
    @Column(name="date_created")
    private Date mDateCreated;

    //the poll this post contains
    @OneToOne
    @JoinColumn(name="poll_id")
    private Poll mPoll;
@Entity
@Table(name="user_feed")
public class Post implements Serializable {
    @Id
    @Column(name="user_id")
    private long mUserId;

    //removed long mPollId
    //hibernate is capable of getting the foreign key for a post's
    //poll_id column from its poll object -- mPoll
    //so i don't have to have a separate field for the id of this post's
    //poll

    @Column(name="is_repost")
    private boolean mIsRepost;

    @Column(name="date_created")
    private Date mDateCreated;

    //made this field part of the composite id instead of long mPollId
    //pretty much the same composite key as before just had to alter
    //my implementation of Post.equals(Object) to use this poll's id
    //instead of this class's mPollId field
    //implementing your own .equals(Object) method is necessary when
    //creating composite keys as i do with multiple @Id annotations
    //i think you also have to implement your own .hashCode() method too
    //but the word hash scares me, so I didn't do it
    //the code works, so i'm just gonna let it rock
    @OneToOne
    @JoinColumn(name="poll_id")
    private Poll mPoll;
投票类别:

@Entity
@Table(name="poll")
public class Poll implements Serializable{

    //the poll's id
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private long mId;

    //id of the user who created the poll
    @Column(name="user_id")
    private long mUserId;

    //the text of the poll's question
    @Column(name="question")
    private String mQuestion;

    //the date the poll was created
    @Column(name="date_created")
    private Date mDateCreated;

    //the answer objects for this poll
    @OneToMany
    @JoinColumn(name="id")
    private List<Answer> mAnswers;
@Entity
@Table(name="poll")
public class Poll implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private long mId;

    @Column(name="user_id")
    private long mUserId;

    @Column(name="question")
    private String mQuestion;

    @Column(name="date_created")
    private Date mDateCreated;

    //removed @JoinColumn -- not completely sure about why it wasn't
    //helping, but many of the examples similar to my use case didn't
    //use it so I got rid of it
    //added mappedBy variable -- still not really sure what it does
    //but it works
    //and added FetchType.EAGER so everytime a Poll object is loaded
    //the answers it's associated with are loaded too
    @OneToMany(mappedBy="mPoll", fetch=FetchType.EAGER)
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.REMOVE})
    private List<Answer> mAnswers;
最终功能查询:是否有效

Session session = HibernateUtilities.openSession();
        session.beginTransaction();


        List<Post> usersFeed = session.createQuery("select p from Post p where p.mUserId = :userId")
                  .setString("userId", userId)
                  .list();


        session.getTransaction().commit();
        session.close();
会话会话=HibernateUtilities.opensession