2009-06-22 10 views
5

Mam jednokierunkową relację @OneToMany pomiędzy drużyną a klasą Gracza. Chciałbym zapisać obiekt drużynowy wśród twoich graczy. Identyfikator gracza ZWIĘKSZY SIĘ przez klucz obcego zespołu i indeks listy w następujący sposób. Mam takie mapowanie, ponieważ muszę zachować drużynę i twoich graczy jedli w tym samym czasie.Klasa zachowująca się jak @Entity i @Embeddable

@Entity 
public class Team { 

    @Id 
    @GeneratedValue 
    private Integer id; 

    @CollectionOfElements 
    @JoinTable(
     name="PLAYER", 
     [email protected](name="TEAM_ID")) 
    @IndexColumn(name="PLAYER_INDEX") 
    private List<Player> playerList = new ArrayList<Player>(); 

} 

@Embeddable 
public class Player { 

    // Player's getter's and setter's 

} 

Więc jeśli mogę użyć następujących

Team team = new Team(); 

team.getPlayerList().add(new Player()); 
team.getPlayerList().add(new Player()); 

session.save(team); // It works! 

Zdarza się, czy używasz @CollectionsOfElements, klasa gracza potrzebujemy @Embeddable adnotacji, a nie @Entity. JPA nie zezwala na @Entity i @Embeddable w tym samym czasie. Gracz jest także @Entity - ma relacje z innymi podmiotami.

Czy ktoś ma pomysł, że mogę zapisać drużynę i gracza (JEDNĄ DROGĘ) za pomocą CascadeType.PERSIST z @Entity w klasie Player zamiast @Embeddable?

Pamiętaj, że kluczem ZWIĄZEK podstawowy musi być przypisany przed zapisaniem ale identyfikator i PlayerList pozycja indeksu zespołu mógłby odgrywać rolę gracza złożonych pierwotnych kluczowych

Pozdrowienia,

Odpowiedz

6

Poniższe rozwiązanie pokazuje klucz złożony dla gracza, który składa się z zespołu i pozycji na liście graczy w tym zespole. Zapisuje kaskadę od zespołu do graczy.

Team.java

import java.io.Serializable; 
import java.util.ArrayList; 
import java.util.List; 

import javax.persistence.CascadeType; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.OneToMany; 
import javax.persistence.Version; 

import org.apache.commons.lang.builder.ToStringBuilder; 
import org.apache.commons.lang.builder.ToStringStyle; 
import org.hibernate.annotations.IndexColumn; 

@Entity 
public class Team implements Serializable { 

    @Id @GeneratedValue private Long id; 

    @Version private int version; 

    @OneToMany(cascade=CascadeType.ALL, mappedBy="id.team") 
    @IndexColumn(name="PLAYER_IDX") 
    private List<Player> players = new ArrayList<Player>(); 

    private String name; 

    protected Team() {} 

    public Team(String name) { 
     this.name = name; 
    } 

    public boolean addPlayer(Player player) { 
     boolean result = players.add(player); 
     if (result) { 
      player.setPlayerId(new PlayerId(this, players.size() - 1)); 
     } 
     return result; 
    } 

    public List<Player> getPlayers() { 
     return players; 
    } 

    @Override 
    public String toString() { 
     return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("name", name).append("players", players).toString(); 
    } 
} 

Player.java

import java.io.Serializable; 

import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.Version; 

import org.apache.commons.lang.builder.ToStringBuilder; 
import org.apache.commons.lang.builder.ToStringStyle; 

@Entity 
public class Player implements Serializable { 

    @Id private PlayerId id; 

    @Version private int version; 

    void setPlayerId(PlayerId id) { 
     this.id = id; 
    } 

    @Override 
    public String toString() { 
     return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("number", id.getNumber()).toString(); 
    } 

} 

PlayerId.java

import java.io.Serializable; 

import javax.persistence.Column; 
import javax.persistence.Embeddable; 
import javax.persistence.ManyToOne; 

import org.apache.commons.lang.builder.HashCodeBuilder; 

@Embeddable 
public class PlayerId implements Serializable { 

    @ManyToOne 
    private Team team; 

    @Column(name="PLAYER_IDX", insertable=false, updatable=false) 
    private int number; 

    protected PlayerId() {} 

    PlayerId(Team team, int number) { 
     this.team = team; 
     this.number = number; 
    } 

    public int getNumber() { 
     return number; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } else if (obj == this) { 
      return true; 
     } if (obj instanceof PlayerId) { 
      PlayerId other = (PlayerId) obj; 
      return other.team.equals(this.team) && other.number == this.number; 
     } 
     return false; 
    } 

    @Override 
    public int hashCode() { 
     return new HashCodeBuilder().append(team).append(number).toHashCode(); 
    } 

} 

Test poniżej:

public void testPersistTeamAndPlayers() throws Exception { 
    Team team = new Team("My Team"); 
    team.addPlayer(new Player()); 
    team.addPlayer(new Player()); 

    AnnotationConfiguration configuration = new AnnotationConfiguration(); 
    configuration.addAnnotatedClass(Team.class); 
    configuration.addAnnotatedClass(Player.class); 
    configuration.configure(); 

    SessionFactory sessionFactory = configuration.buildSessionFactory(); 
    Session session; 
    session = sessionFactory.openSession(); 
    Transaction transaction = session.beginTransaction(); 
    session.save(team); 
    transaction.commit(); 
    session.close(); 

    session = sessionFactory.openSession(); 
    @SuppressWarnings("unchecked") List<Team> list = session.createCriteria(Team.class).list(); 
    assertEquals(1, list.size()); 

    Team persisted = list.get(0); 
    System.out.println(persisted); 

daje następujące dane wyjściowe dziennika:

12:37:17,796 DEBUG [SchemaExport, SchemaExport.execute] 
    create table Player (
     PLAYER_IDX integer not null, 
     version integer not null, 
     team_id bigint, 
     primary key (PLAYER_IDX, team_id) 
    ) 
12:37:17,796 DEBUG [SchemaExport, SchemaExport.execute] 
    create table Team (
     id bigint generated by default as identity (start with 1), 
     name varchar(255), 
     version integer not null, 
     primary key (id) 
    ) 
12:37:17,796 DEBUG [SchemaExport, SchemaExport.execute] 
    alter table Player 
     add constraint FK8EA38701AA5DECBA 
     foreign key (team_id) 
     references Team 
12:37:17,812 INFO [SchemaExport, SchemaExport.importScript] Executing import script: /import.sql 
12:37:17,812 INFO [SchemaExport, SchemaExport.execute] schema export complete 
12:37:17,859 DEBUG [SQL, SQLStatementLogger.logStatement] 
    insert 
    into 
     Team 
     (id, name, version) 
    values 
     (null, ?, ?) 
12:37:17,875 DEBUG [SQL, SQLStatementLogger.logStatement] 
    call identity() 
12:37:17,875 DEBUG [SQL, SQLStatementLogger.logStatement] 
    select 
     player_.PLAYER_IDX, 
     player_.team_id, 
     player_.version as version1_ 
    from 
     Player player_ 
    where 
     player_.PLAYER_IDX=? 
     and player_.team_id=? 
12:37:17,890 DEBUG [SQL, SQLStatementLogger.logStatement] 
    select 
     player_.PLAYER_IDX, 
     player_.team_id, 
     player_.version as version1_ 
    from 
     Player player_ 
    where 
     player_.PLAYER_IDX=? 
     and player_.team_id=? 
12:37:17,890 DEBUG [SQL, SQLStatementLogger.logStatement] 
    insert 
    into 
     Player 
     (version, PLAYER_IDX, team_id) 
    values 
     (?, ?, ?) 
12:37:17,890 DEBUG [SQL, SQLStatementLogger.logStatement] 
    insert 
    into 
     Player 
     (version, PLAYER_IDX, team_id) 
    values 
     (?, ?, ?) 
12:37:17,906 DEBUG [SQL, SQLStatementLogger.logStatement] 
    select 
     this_.id as id0_0_, 
     this_.name as name0_0_, 
     this_.version as version0_0_ 
    from 
     Team this_ 
12:37:17,937 DEBUG [SQL, SQLStatementLogger.logStatement] 
    select 
     players0_.team_id as team3_1_, 
     players0_.PLAYER_IDX as PLAYER1_1_, 
     players0_.PLAYER_IDX as PLAYER1_1_0_, 
     players0_.team_id as team3_1_0_, 
     players0_.version as version1_0_ 
    from 
     Player players0_ 
    where 
     players0_.team_id=? 
Team[name=My Team,players=[Player[number=0], Player[number=1]]] 

Ostatni wiersz pokazuje toString dla Team i Player, która pokazuje, jak numery są przypisane (indeks listy). Inne podmioty mogą polecać gracza (według team_id i player_idx).

+0

Gratulacje, Maarten. Dobra odpowiedź. –

0

zrobiłeś jakieś błędy czuję.

@Embedded to sposób reprezentowania obiektu/komponentu z wybranych pól w tabeli. Możesz go użyć do reprezentowania kluczy złożonych, ale musisz także użyć @EmbeddedId.

Patrząc na to, co próbujesz osiągnąć, czuję, że możesz się tam dostać dzięki znacznie prostszemu mapowaniu. (kilka części pominięto dla zwięzłości)

@Entity 
public class Team { 

    @OneToMany(mappedBy="team") 
    private List<Player> playerList = new ArrayList<Player>(); 

} 

@Enity 
public class Player { 

    @ManyToOne 
    @JoinColumn(name="TEAM_ID") 
    private Team team; 

} 

Jeśli odtwarzacz jest dołączyć/link tabelę można użyć @Embedded statycznych klasy do reprezentowania klucza kompozytowego, zobacz książkę Java Persistence z JPA celu uzyskania dalszych informacji na ten temat.

Powiązane problemy