views:

166

answers:

1

Hi,

Take a look at the following classes (UNIdirectional @OneToMany)

@Entity
public class Team {

    private Integer id = -1;

    @Id
    @GeneratedValue
    public Integer getId() {
        return this.id;
    }

    private List<Player> playerList;


    @OneToMany
    @Cascade(CascadeType.SAVE_UPDATE)
    @JoinColumn(name="TEAM_ID", insertable=false, updateable=false)
    public List<Player> getPlayerList() {
        return this.playerList;
    }

    public void addPlayer(Player player) {
        player.setId(new PlayerId(getId(), getPlayerList().size()));

        playerList.add(player);
    }

}

Notice addPlayer: team's id and player's teamId references the same instance so

AssertEquals(team.getId(), player.getPlayerId().getTeamId());

should work, don't ?

Hibernate will not save -1 value because i have declared a generator strategy (default to auto) If an identifier generator is declared, Hibernate takes care of the primary key value assignment. I have assined -1 to Team's id IN ORDER TO SHARE ITS REFERENCE in Player's id (when calling addPlayer method) as follows

@Embeddable
public class PlayerId implements Serializable {

    private Integer teamId;

    private Integer playerIndex;

    // required no-arg constructor
    public PlayerId () {}

    public PlayerId(Integer teamId, Integer playerIndex) {
        this.teamId = teamId;
        this.playerIndex = playerIndex;
    }

    @Column(name="TEAM_ID", nullable=false)
    public Integer getTeamId() {
        return this.teamId;
    }

    @Column(name="PLAYER_INDEX", nullable=false)
    public Integer getPlayerIndex() {
        return this.playerIndex;
    }

    // getters and setters

    public boolean equals(Object o) {
        if(o == null)
            return false;

        if(!(o instanceof PlayerId))
            return false;

        PlayerId other = (PlayerId) o;
        if(!(getTeamId().equals(other.getTeamId()))
            return false;

        if(!(getPlayerIndex().equals(other.getPlayerIndex()))
            return false;

        return true;
    }

}

But when i call (Take a special look at addPlayer)

Team team = new Team();

Player player = new Player();

// teamId property in PlayerId references Team id
team.addPlayer(player);

session.save(team);

And i see the database i get

PLAYER
TEAM_ID     PLAYER_INDEX
-1          0

TEAM
ID
1

And when i compare after saving

AssertEquals(team.getId(), player.getPLayerId().getTeamId()); // It does not works! why ?

log outputs

INSERT INTO TEAM VALUES()

// SELECT BEFORE SAVING OR UPDATING WHEN USING A COMPOUND PRIMARY KEY
SELECT * FROM PLAYER WHERE TEAM_ID = ? AND PLAYER_INDEX = ?

INSERT INTO PLAYER (TEAM_ID, PLAYER_INDEX) VALUES (?, ?)

So do you know why Hibernate lost Team's id reference in Player's teamId property after saving a team and its players ?

+1  A: 

I'm not sure what you mean by "maintain references"? I'm also not quite clear on what you're trying to do here...

Did you expect Hibernate to use the TEAM_ID of newly created Team entity (e.g. 1 in this case) to insert Player instances? If so, you've specifically prevented that from happening by specifying insertable / updatable as false in @JoinColumn declaration - you need to move them to getTeamId() method within Player class instead.

Can you clarify what you're trying to achieve here?

ChssPly76
Hi Chss, added to question.
Arthur Ronald F D Garcia
You can't "share" a reference to an Integer. It's immutable, so when TeamId value changes (and it is changed by Hibernate when Team instance is saved), a brand new Integer instance is created. Thus you end up with "1" in Team.id and your old "-1" in PlayerId.teamId. The way to fix this, as I said in my answer, is to move insertable="false", updatable="false" to PlayerId.getTeamId() annotation.
ChssPly76
It shouldn't because it's a composite id (meaning it's assigned) and teamId will be set (and inserted / updated) by association. But I'm not 100% sure on this - I tend to always go with surrogate keys as they present a lot less headache; doubly so for associations.
ChssPly76
I think it does not work because it a key in a compound primary key. I have seen http://commons.apache.org/lang/apidocs/org/apache/commons/lang/mutable/MutableInt.html A mutable integer. Anyway, thank you.
Arthur Ronald F D Garcia
It really does not work. You can not put insertable=false, updateable=false in a compound primary key.
Arthur Ronald F D Garcia