如何使用休眠模式查询具有嵌套对象的嵌套对象,该嵌套对象具有嵌套的对象集合 [英] How to use hibernate to query for an object with a nested object that has a nested collection of objects
问题描述
使用Hibernate,我需要在MySQL数据库中查询与Poll实体具有一对一关系的Post实体,而该Poll实体与Answer实体具有一对多的关系.我需要Post对象包含Poll对象,而其Poll对象包含Answer对象.这是基本的类设置:
Using Hibernate, I need to query a MySQL database for a Post entity that has a one-to-one relationship with a Poll entity that has a one-to-many relationship with an Answer entity. I need the Post object to contain the Poll object and its Poll object to contain its Answer objects. Here's the basic class setup:
更新: Post表必须没有主键列.这是浪费数据.我需要能够使用user_id列从数据库中获取Post对象.使用user_id列获取Post对象是完成此操作的唯一方法,因此,对于我来说,拥有主键列是没有意义的.因此,如果您要提供一个答案,以深入了解解决 我 问题的解决方案,请牢记这些规格.
Update: The Post table must not have a primary key column. It is a waste of data. I need to be able to get Post objects from the database using the user_id column. Getting Post objects using the user_id column is the only way it will ever be done, so it makes no sense for me to have a primary key column. So if you're going to provide an answer that provides insight into a solution that solves my problem, please keep those specifications in mind.
邮政课:
@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="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="answer")
public class Answer implements Serializable {
//id for a particular answer
//*this is not a necessary value for the application logic, but
//*Hibernate forces me to designate an @Id annotation for every
//*entity, so I created this field and the associated column in
//*the database
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private long mId;
//the answer's text
@Column(name="answer_text")
private String mAnswer;
//the id of the poll to which this answer pertains to
@Column(name="poll_id")
private long mPollId;
***我对此表的ID感到困惑.每个答案都有一个主键是没有意义的,但是Hibernate在类中需要某种@Id注释,因此我决定为了Hibernate在表中创建一个主键列.它从未使用过.我想摆脱它,但是除了当前的文本外,实际上没有什么可以使一个Answer对于同一民意测验在另一个答案中独树一帜–应用逻辑不是必需的.
***I'm confused about the id for this table. It doesn't make sense for each answer to have a primary key, but Hibernate requires some sort of @Id annotation in the class, so I decided to just create a primary key column in the table for the sake of Hibernate. It's never used. I would like to get rid of it, but there really isn't anything that makes one Answer unique from another for the same poll except for their text at the moment -- it's not necessary for the application logic.
我想出的查询:不起作用
Query I came up with: doesn't work .
这个查询实际上只是我的测试,以查看是否可以获取一个带有所有嵌套对象的Post对象.我知道我能不能得到一个,一个收藏就不会花太多时间了,但是我什至无法得到一个.
This query was really just me testing to see if I could get a single Post object with all of its nested objects. I knew if I could get one, getting a collection wouldn't be much more of a stretch -- but I can't even get one.
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);
推荐答案
我自己解决了这个问题.以下代码中的所有注释都指定了我对问题中提出的代码所做的更改,并解释了为什么要进行更改.
Solved it myself. All the comments in the below code designate the changes I made to the code I presented in the question and explain why I made them.
邮政课:
@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{
@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;
答案课:
@Entity
@Table(name="answer")
public class Answer implements Serializable {
//turns out having a primary key on the answer table is actually useful
//for the application logic. would you look at that
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private long mId;
@Column(name="answer_text")
private String mAnswer;
//got rid of long mPollId
//it was for the same reason i did in the Post class
//hibernate does the work for me with the mPoll object and the
//annotations i've provided on it
//made the relationship between a poll and its answers bidirectional
//not entirely sure how adding the below annotations to the new
//Poll field fixed my problems, but it did
//i imagine it somehow tells hibernate that the primary key
//for the below object is the foreign key represented by poll_id in the
//database table for this entity
//and making insertable=true enables hibernate to insert that foreign
//key into the appropriate column in the database when this entity
//is saved
//updatable seemed to be necessary
//hibernate complained when it wasn't there
//and nullable was in the helpful examples i found so it was copy and
//pasted along with the rest of the helpful stuff here
//this field can't be nullable anyways so semantically, it makes sense
//for it to be there
@ManyToOne
@JoinColumn(name="poll_id", nullable = false, insertable=true, updatable=false)
private Poll mPoll;
最终功能查询:确实有效
Final functioning query: does work
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();
这篇关于如何使用休眠模式查询具有嵌套对象的嵌套对象,该嵌套对象具有嵌套的对象集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!