0

I have two classes :

@Entity
public class Player
{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String nick;

    @ManyToOne
    private Team team;
}

and

@Entity
public class Team
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;

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

    @Transient
    public void addPlayer(Player player)
    {
        if (player != null)
            players.add(player);
    }
}

and in controller I add one team and one player to database

private void addTeams()
    {
        Team team = new Team();
        team.setName("Name"); 

        Player p = new Player();
        team.addPlayer(p);
        teamsService.addTeam(team);  
        playersService.addPlayer(p); 
    }  

Abstact Dao class :

package eniupage.domain.repository.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.inject.Inject;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;

import eniupage.domain.repository.Dao;

public abstract class DaoImpl<T> implements Dao<T>
{
    @Inject
    private SessionFactory sessionFactory;

    private Class<T> domainClass;

    protected Session currentSession()
    {
        return sessionFactory.getCurrentSession();

    }

    @SuppressWarnings("unchecked")
    private Class<T> getDomainClass()
    {
        if (domainClass == null)
        {
            ParameterizedType thisType = (ParameterizedType) getClass().getGenericSuperclass();
            this.domainClass = (Class<T>) thisType.getActualTypeArguments()[0];
        }
        return domainClass;
    }

    private String getDomainClassName()
    {
        return getDomainClass().getName();
    }

    @Transactional
    public void add(T t)
    {
        currentSession().save(t);
    }

    @Transactional
    @SuppressWarnings("unchecked")
    public List<T> getAll()
    {
        return currentSession().createQuery("from " + getDomainClassName()).list();
    }

    @Transactional
    @SuppressWarnings("unchecked")
    public T get(Serializable id)
    {
        return (T) currentSession().get(getDomainClass(), id);
    }

    @Transactional
    @SuppressWarnings("unchecked")
    public T load(Serializable id)
    {
        return (T) currentSession().load(getDomainClass(), id);
    }

    @Transactional
    public long count()
    {
        return (Long) currentSession().createQuery("select count(*) from " + getDomainClassName()).uniqueResult();
    }
}

I added to hibernate config hibernate.hbm2ddl.auto as create-drop

In result I got two tables:

  • Team table
  • Player table with column team_id which is null.

Why team_id is null ? I did team.addPlayer(p)

Bambelal
  • 179
  • 1
  • 2
  • 13

3 Answers3

0

you have to set the team of that player, as it was mappedBy team entity.

public void addPlayer(Player player)
{
    if (player != null) {
        player.setTeam(this);  // here is the change
        players.add(player);
    }
}

or change following

 Player p = new Player();
 p.setTeam(team);    // here is the change 
 team.addPlayer(p);
Nikson Kanti Paul
  • 3,394
  • 1
  • 35
  • 51
  • That is because in JPA world, the owner of the relation is responsible for setting the mapping keys. You did specify the owner of the relation to be Player by setting ``mappedBy`` attribute. Yes, I know, it is defined exactly the opposite than with relational mapping. – gmaslowski May 17 '16 at 18:32
  • I didn't set anything `mappedBy`. OP did but he doesn't set the parent of `Player` by setting a `team` – Nikson Kanti Paul May 17 '16 at 18:36
  • I saw tutorial where somebode used EntityMenager.persist( ) instead of Session.save ( ) and there works my way. Hmm .. – Bambelal May 17 '16 at 18:37
  • Yeah sorry. I was commenting on your answer because I agree with it and wanted just to specify why it has to be done just like you did :). With 'you' in the comment I was actually referring to author of the question. Sorry for misleading. I can't edit the comment anymore :(. – gmaslowski May 17 '16 at 18:38
  • @Bambelal, persist will give exception when object is [`Detached`](http://stackoverflow.com/a/18600952/1225337) – Nikson Kanti Paul May 17 '16 at 18:42
  • @gmaslowski so why it works when I set team in player but dont when set(add) player to team ? – Bambelal May 18 '16 at 08:19
  • it's totally depends on your strategy, how you are managing `parent-child` relation, read more about `unidirectional-bidirectional mapping of parent-child relation` – Nikson Kanti Paul May 18 '16 at 10:02
0

If have a bidirectional relationship, then you must always set both ends of the relationship.

private void addTeams()
        {
            Team team = new Team();
            team.setName("Name"); 

            Player p = new Player();
            p.setTeam(team); 
            team.addPlayer(p);
            teamsService.addTeam(team);  
            playersService.addPlayer(p); 
        }  

Also, You have to provide Cascade Type in mapping.

@OneToMany(mappedBy = "team",cascade = CascadeType.PERSIST)
private List<Player> players = new ArrayList<>();
AsSiDe
  • 1,826
  • 2
  • 15
  • 24
0

People in tutorials never set both ends of the relationship and their code works fine ( for example https://www.youtube.com/watch?v=jAi8bY-H_ek ) :)

When I use player.setTeam(team) instead of team.addPlayer(player) it works ( column isn't NULL ) ..

Bambelal
  • 179
  • 1
  • 2
  • 13