Java JPA один ко многим - PullRequest
       26

Java JPA один ко многим

3 голосов
/ 03 марта 2011

Я недавно опубликовал сообщение о заполнении JTable, который теперь полностью функционален. Как бы то ни было, сейчас я застрял над чем-то другим, и я надеюсь достичь двух конкретных оттенков в этой теме.

Один - решить мою проблему, а другой - иметь готовый ответ, когда другие сталкиваются с той же проблемой, потому что я так и не нашел правильного ответа.

У меня есть следующий сценарий

Два стола:

игр
id pk int
жанр int
название варчар ....

жанр
id pk int
имя варчар ..

Одна игра может иметь только один жанр, но один жанр может содержать много игр.

Я использую 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, title, genre-name, publisher-name, Releaseate

В моем 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 и что он этого не делает из-за определенного отношения.

Я все еще новичок, поэтому, пожалуйста, будьте нежны ^^

Спасибо за ваше время.

Ответы [ 3 ]

2 голосов
/ 03 марта 2011

Чтобы немного приблизиться к проблеме, вы можете включить детализированное ведение журнала JPA, добавив следующее в ваш файл persistence.xml (внутри элемента единицы постоянства):

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

Затем просмотрите ваш лог-файл и посмотрите, как jpql-запрос переводится в sql.

Другая идея (может показаться глупой!): Вы установили ограничения внешнего ключа в базе данных тоже или только в модуле постоянства?

Надеюсь, это поможет

1 голос
/ 03 марта 2011

Ответ был решен.

Проблема, с которой я столкнулся, и причина, по которой я ничего не получил, заключалась в том, что значение было нулевым.Это была моя грубая ошибка в базе данных.По какой-то причине я добавил запись к идентификатору жанра 2, а не к идентификатору 1, в то время как игра имела идентификатор жанра 1, который был пустым

(спасибо, Крис Бабич):)

Так что мойЦенный урок дня: Результаты проверки дубликатов в базе данных, посмотрите, есть ли у вас соответствующие записи.Используйте

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

При отладке

И я добавил функциональность вставки.Спасибо вам за это, Хорхе.

Спасибо, что нашли время ответить и прочитать.

Так что, к сожалению, отношения работают очень хорошо с использованием JPA.ALOT лучше, чем linq to sql, на мой взгляд.

Теперь я могу назвать следующее:

game.getPublisherBean().getPublisher();

И я получаю желаемый результат.Так что «РПГ» вместо «»

1 голос
/ 03 марта 2011

Вы уверены, что делаете вкладыши?может случиться так, что когда вы вставляете игру, вам нужно вставить жанр в список и обновить игру примерно так:

/**** 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);

, тогда вам нужно взять уже существующую сущность и установить для каждого объекта, потому чтоотношение является двунаправленным, примерно так*

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

Этот запрос возвращает коллекцию объектов [] в позиции 0, имеет жанр и позицию 1 в игре

...