Моделирование двух многим отношения в JPA/Hibernate

У меня есть следующая проблема связи сущностей. "Игра" должна иметь два (и только два) объекты "Команды". У "Команды" может быть много "Игр"

Это, насколько я вижу, является отношениями Two-Many. Однако... Я не знаю, как смоделировать это в JPA. Например, я собирался сделать что-то вроде этого...

@Entity
public class Team extends BaseObject {
  private Long id;
  private Set<Game> games;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO) 
  public Long getId() {return id;}
  public void setId(Long id) {this.id = id;}

  @OneToMany(mappedBy = "game")
  public Set<Game> getGames() {return games;}
  public void setGames(Set<Game> games) {this.games = games;}
}

@Entity
public class Game extends BaseObject {
  private Long id;
  private Team team1;
  private Team team2;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO) 
  public Long getId() {return id;}
  public void setId(Long id) {this.id = id;}

  @ HERE IS THE PROBLEM - WHAT ANNOTATION DO I USE?
  public Team getTeam1() {return team1;}
  public void setTeam1(Team team1) {this.team1 = team1;}

  @ HERE IS THE PROBLEM - WHAT ANNOTATION DO I USE?
  public Team getTeam2() {return team2;}
  public void setTeam2(Team team1) {this.team2 = team2;}
}

Но, как Вы видите, я не уверен, как соединить таблицы со стороны аннотации. Кто-либо когда-либо делал что-то вроде этого прежде? Какие-либо идеи, справка?

спасибо очень!

10
задан Brian 1 February 2010 в 15:56
поделиться

4 ответа

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

  1. Измените способ моделирования отношений. Например, у вас может быть что-то вроде:

    @Энтититити.
    общественный класс Принадлежность к игре
     Команда;
     Игровая игра;
     int gamePosition; // Если для вас важно отслеживание команды 1 против команды 2
    }
    

    , а затем Игра имеет Коллекция , т.е. вы моделируете ее как много-много-много. Игра все еще может иметь удобные методы для настройки команд 1 и 2 и т.д. (бизнес-логика, чтобы закрепить, что есть только 2 команды, как бы это ни было сделано), но они переносятся обратно в коллекцию Collection, используемую в спящем режиме.

  2. Отказаться от двунаправленности отношений - выбрать одно направление (ИграКоманда кажется наиболее подходящим) и вздремнуть только в этих отношениях. Поиск Игры в которых участвует Команда становится операцией из вашего DAO и т.д., а не тем, что доступно из самого Команды :

    публичного класса GameDAO {
     ....
     публичная коллекция <Игра> игрыForTeam(Team t) {
     ....
     Запрос q = session.createQuery("FROM Game WHERE team1 = :team OR team2 = :team");
     q.setParameter("команда", t);
     return q.list();
     }
    }
    

    или что-то подобное...

  3. Продолжайте движение по маршруту, но "жульничайте" в конце команды . Свойства на стороне Игры должны быть отображены как нормальные многопользовательские отношения; затем используйте mappedBy в конце Team, чтобы указать, что Игра 'контролирует' отношения.

    public class Team {
     ...
     @OneToMany(mappedBy="team1")
     private Set team1Games;
     @OneToMany(mappedBy="team2")
     private Set team2Games;
    

    и затем имеют свойство удобства для вашего API (team1Games и team2Games только для использования в спящем режиме):

     @Transient
     public Set getGames() {
     Set allGames = new HashSet(team1Games);
     allGames.addAll(team2Games);
     // Или используйте Google-коллекции Sets.union() для получения бонусных очков.
     вернуть AllGames;
     }
    

    так что для абонентов вашего класса прозрачно, что есть 2 свойства.

6
ответ дан 4 December 2019 в 01:00
поделиться

PC-Lint может помочь, это как Findbugs для C++. Это коммерческий продукт, но есть гарантия возврата 30 денег.

-121--3223146-

Можно предоставить собственную функцию сортировки list.sort () :

Метод sort () принимает необязательные аргументы для управления сравнениями.

  • cmp задает пользовательскую функцию сравнения двух аргументов (перечислять предметов), которая должна возвращать отрицательное, нулевое или положительное число в зависимости от того, считается ли первый аргумент меньшим, равным или большим, чем второй аргумент: cmp = lambda x, y: cmp (x.lower (), y.lower ()) . Значение по умолчанию - Нет .

  • key указывает функцию одного аргумента, который используется для извлечения ключа сравнения из каждого элемента списка: key = str.lower . Значение по умолчанию - Нет .

  • reverse является логическим значением. Если установлено значение True, элементы списка сортируются так, как если бы каждое сравнение было отменено.

В общем случае процессы преобразования ключей и обратного преобразования намного быстрее, чем задание эквивалентной функции cmp. Это происходит потому, что cmp вызывается несколько раз для каждого элемента списка, в то время как клавиша и обратная клавиша касаются каждого элемента только один раз.

-121--789211-

Я думаю, что у вас есть две отношения один ко многим, а не одно два ко многим.

1
ответ дан 4 December 2019 в 01:00
поделиться

У вас есть отношения @Onetomany (я полагаю, игра имеет отношения @manytoOne с командой), мой совет:

Используйте инкапсуляцию, чтобы получить вашу цель

@Entity
public class Team {

    private Game game1;
    private Game game2;

    private List<Game> gameList = new ArrayList<Game>();

    public void setGame1(Game game1) {
        // You can use index 0 to store your game1
        if(getGameList().size == 0)
            getGameList().add(game1);
        else
            getGameList().set(0, game1);
    }

    @Transient
    public Game getGame1() {
        if(getGameList().size() == 0)
            return null;

        return getGameList().get(0);
    }

    public void setGame2(Game game2) {
        // You can use index 1 to store your game2
        switch(getGameList().size()) {
            case 0:
                getGameList().add(null);

                getGameList().add(game2);
            break;
            case 1:
                getGameList().add(game2);
            break;
            case 2:
                getGameList().set(1, game2);
            break;
        }
    }

    @Transient
    public Game getGame2() {
        if(getGameList().size() < 2)
            return null;

        return getGameList().get(1);
    }

    @OneToMany
    @JoinColumn(name="TEAM_ID")
    public List<Game> getGameList() {
        return this.gameList;
    }

}

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

С уважением,

2
ответ дан 4 December 2019 в 01:00
поделиться

Подумайте, что произойдет, если в ваших играх будет первый игрок - команда (выбранная из списка команд), а второй игрок - компьютер (выбран из списка компьютеров):

  • Ваш первый игрок будет внешним ключом в таблице команд.
  • Ваш второй игрок будет внешним ключом в таблице компьютеров.

Если вы теперь замените «компьютер» как игрока другой «командой», вы получите два внешних ключа в таблице команд.

Мой JPA немного устарел, но я считаю, что вы моделируете отношения внешнего ключа с помощью аннотации @OneToOne , например:

@OneToOne(cascade = {CascadeType.ALL}, optional = false)
@JoinColumn(name = "team1")

и второй:

@OneToOne(cascade = {CascadeType.ALL}, optional = false)
@JoinColumn(name = "team2")
2
ответ дан 4 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: