Java JPA 一对多

发布于 2024-10-20 06:24:22 字数 2859 浏览 1 评论 0原文

我最近发布了有关填充 JTable 的文章,该 JTable 现在功能齐全。 然而,我现在被其他事情困住了,我希望通过这个线程实现两个特定的事情。

一是解决我的问题,二是当其他人遇到同样的问题时准备好答案,因为我还没有找到正确的答案。

我有以下场景

两个表:

游戏
id pk 整数
类型整数
标题 varchar ....

流派
id pk 整数
name varchar ..

一款游戏只能有一种类型,但一种类型可以包含许多游戏。

我使用 Eclipse 作为我的 IDE,使用 eclipselink 作为我的 JPA 提供程序。

我已经使用 Eclipse 提供的实体向导生成了类,它还允许我定义两个表之间的关系。

关系如下:

@Entity
@Table(name="games")
public class Game implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(name="Id", unique=true, nullable=false)
private int id;

@Temporal( TemporalType.DATE)
@Column(name="AddDate", nullable=false)
private Date addDate;

@Lob()
@Column(name="Description", nullable=false)
private String description;

@Temporal( TemporalType.DATE)
@Column(name="ModifiedDate", nullable=false)
private Date modifiedDate;

@Temporal( TemporalType.DATE)
@Column(name="ReleaseDate", nullable=false)
private Date releaseDate;

@Column(name="Title", nullable=false, length=255)
private String title;

//bi-directional many-to-one association to Genre
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="Genre", nullable=false)
private Genre genreBean;

//bi-directional many-to-one association to Publisher
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="Publisher", nullable=false)
private Publisher publisherBean;

和流派

@Entity
@Table(name="genres")
public class Genre implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(name="Id", unique=true, nullable=false)
private int id;

@Column(name="Genre", nullable=false, length=150)
private String genre;

//bi-directional many-to-one association to Game
@OneToMany(mappedBy="genreBean")
private List<Game> games;

我使用以下内容来选择所有游戏

        List<Game> games;

    try{
        TypedQuery<Game> selectGamesQuery = entityManager.createQuery("SELECT g FROM Game g", Game.class);
        games = selectGamesQuery.getResultList();
    } catch(Exception e) {
        games = null;
        System.out.println(e);

这里的问题是,列表游戏不包含流派名称,实际上,它是空的。

如何配置列表以包含具有以下属性的游戏:id、标题、流派名称、发行商名称、发布日期

在我的 JTable 中,我尝试了以下操作:

        switch(columnIndex){
        case 0:
            return game.getTitle();
        case 1:
            return game.getPublisherBean().getPublisher();
        case 2:
            return game.getGenreBean().getGenre();
        case 3:
            return game.getReleaseDate();
    }

在本例中,在我的 JTable 中,情况 1 的列和 2 个是空的,而其余的则可以工作。

所以我的表格内容看起来像

Battlefield 3 empty empty 3-3-2011

我认为我应该提供足够的信息。

请让我知道代码或选择查询中是否有任何错误或错误,因为我什至找不到我是否必须编写显式 JOIN 查询,并且由于定义的关系,它不会这样做。

我还是个菜鸟,所以请温柔一点^^

谢谢你的时间。

I had recently posted someone about populating a JTable, which is now fully functional.
How ever, I am stuck over something else now, I'm hoping to achieve two specific thigns with this thread.

One is to solve my problem, and the other is to have an answer ready for when others stumble across the same problem, cause I never found a proper answer to this yet.

I have the following scenario

Two tables:

games
id pk int
genre int
title varchar ....

genre
id pk int
name varchar ..

One game can only have one genre, but one genre can contain many games.

I'm using Eclipse as my IDE and eclipselink as my JPA provider.

I have generated the classes with the entity wizard provided by eclipse, whom also allowed me to define relationships between the two tables.

The relationships look as follows:

@Entity
@Table(name="games")
public class Game implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(name="Id", unique=true, nullable=false)
private int id;

@Temporal( TemporalType.DATE)
@Column(name="AddDate", nullable=false)
private Date addDate;

@Lob()
@Column(name="Description", nullable=false)
private String description;

@Temporal( TemporalType.DATE)
@Column(name="ModifiedDate", nullable=false)
private Date modifiedDate;

@Temporal( TemporalType.DATE)
@Column(name="ReleaseDate", nullable=false)
private Date releaseDate;

@Column(name="Title", nullable=false, length=255)
private String title;

//bi-directional many-to-one association to Genre
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="Genre", nullable=false)
private Genre genreBean;

//bi-directional many-to-one association to Publisher
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="Publisher", nullable=false)
private Publisher publisherBean;

and the genre

@Entity
@Table(name="genres")
public class Genre implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(name="Id", unique=true, nullable=false)
private int id;

@Column(name="Genre", nullable=false, length=150)
private String genre;

//bi-directional many-to-one association to Game
@OneToMany(mappedBy="genreBean")
private List<Game> games;

I use the following to select all games

        List<Game> games;

    try{
        TypedQuery<Game> selectGamesQuery = entityManager.createQuery("SELECT g FROM Game g", Game.class);
        games = selectGamesQuery.getResultList();
    } catch(Exception e) {
        games = null;
        System.out.println(e);

The problem here is, List games does not contain the genre name, actually, it is empty.

How do I configure the list to contain a game that has the following attributes: id, title, genre-name, publisher-name, releasedate

In my JTable I have tried the following:

        switch(columnIndex){
        case 0:
            return game.getTitle();
        case 1:
            return game.getPublisherBean().getPublisher();
        case 2:
            return game.getGenreBean().getGenre();
        case 3:
            return game.getReleaseDate();
    }

In this case, in my JTable the columns for case 1 and 2 are empty, while the rest works.

So my table content looks like

Battlefield 3 empty empty 3-3-2011

I think with this I should have provided enough info.

Please let me know if there is any mistake or error in the code, or perhaps the select query, as I couldn't even find if I HAVE to write an explicit JOIN query and that it doesnt do that due to the defined relationship.

I'm still a noobie, so please be gentle ^^

Thank you for your time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海蓝天 2024-10-27 06:24:22

为了更接近问题,您可以通过在 persistence.xml(在 persistence-unit 元素内)中添加以下内容来启用细粒度 JPA 日志记录:

<properties>
      <property name="eclipselink.logging.level" value="FINEST"/>
</properties>

然后观察日志文件并查看 jpql-query 如何转换为 sql。

另一个想法(可能听起来很愚蠢!):您是否也在数据库中设置了外键约束,还是仅在持久性单元中设置了外键约束?

希望这有帮助

to get a bit closer to the problem you could enable finegrained JPA logging by adding the following in your persistence.xml (inside a persistence-unit element):

<properties>
      <property name="eclipselink.logging.level" value="FINEST"/>
</properties>

Then watch your log file and look how the jpql-query gets translated to sql.

Another idea (may sound stupid!): Did you set the foreign key constraints in the database too or only in Persistence Unit?

Hope this helps

影子是时光的心 2024-10-27 06:24:22

你确定你是如何做插入的吗?因为可能会发生这样的情况,当您插入游戏时,您需要在列表中插入类型并更新游戏,

/**** the var em is the entity manager ****/

Game game = new Game();

game.setId(1);
game.setDesription("This is a example");
game.setTitle("try");
em.persist(game);

Genre genre = new Genre();

genre.setName("blah");
genre.setId(1);

em.persist(genre);

这样您就需要将已经持久化的实体设置为每个对象,因为关系是双向的
像这样的东西

genre.getGenreBean().add(game);
em.persist(genre);

我希望这个例子可以帮助您解决问题

编辑:

如果您需要查询,它是这样的

select G, Game from Genre, IN(g.getGenreBean()) Game

这个查询返回位置 0 的 Object[] 集合,具有流派和位置 1 游戏

are you sure about how you are doing the inserts?? because could happen that when you insert the game you need to insert the genre in the list and update the game someting like this

/**** the var em is the entity manager ****/

Game game = new Game();

game.setId(1);
game.setDesription("This is a example");
game.setTitle("try");
em.persist(game);

Genre genre = new Genre();

genre.setName("blah");
genre.setId(1);

em.persist(genre);

then you need to take the entity already persistence and set to each object because the relation is bidirectional
something like this

genre.getGenreBean().add(game);
em.persist(genre);

i hope that this example help you with the problem

EDIT:

If you need the query it's something like this

select G, Game from Genre, IN(g.getGenreBean()) Game

This query return a Collection of Object[] in the position 0 have the genre and the position 1 the game

仙气飘飘 2024-10-27 06:24:22

答案已经解决了。

我遇到的问题以及我没有得到任何东西的原因是因为该值为空。这是我自己在数据库中犯的一个非常草率的错误。由于某种原因,我向流派 id 2 添加了一条记录,而不是 id 1,而游戏的流派 id 为 1,它是空的

(谢谢 Kris Babic):)

所以我今天的宝贵教训是:双重检查结果数据库,看看是否有匹配的记录。 使用

    <properties>
      <property name="eclipselink.logging.level" value="FINEST"/>
   </properties>

调试时

并且我添加了插入功能。谢谢你的豪尔赫。

感谢您花时间回答和阅读。

显然,使用 JPA 可以很好地实现这些关系。在我看来,比 linq to sql 好得多。

我现在可以调用以下内容:

game.getPublisherBean().getPublisher();

我得到了想要的结果。所以“RPG”而不是“”

The answer has been resolved.

The problem I had, and the reason I didnt get anything, was because the value was null. It was a very sloppy mistake of my own in the database. I added a record to genre id 2 for some reason rather then id 1 while the game had a genre id of 1, which was empty

(thank you Kris Babic) :)

So my valueable lesson of the day is: Dubble check results in the database, see if you have matching records. Use

    <properties>
      <property name="eclipselink.logging.level" value="FINEST"/>
   </properties>

When debugging

And I have added insert functionality. So thank you for that Jorge.

Thanks for taking the time to answer and read.

So apperantly, the relationships work very nicely using JPA. ALOT nicer then linq to sql in my opinion.

I can now call the following:

game.getPublisherBean().getPublisher();

And I get the wanted result. So "RPG" instead of ""

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文