【问题标题】:Hibernate @OneToMany and @ManyToOne relationship works wrongHibernate @OneToMany 和 @ManyToOne 关系工作错误
【发布时间】:2016-05-17 18:22:10
【问题描述】:

我有两门课:

@Entity
public class Player
{

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

    private String nick;

    @ManyToOne
    private Team team;
}

@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);
    }
}

在控制器中,我将一支球队和一名球员添加到数据库中

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

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

抽象道类:

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();
    }
}

我添加到休眠配置 hibernate.hbm2ddl.autocreate-drop

结果我得到了两个表:

  • 团队表
  • team_id 列为空的玩家表。

为什么 team_id 为 null ?我做了team.addPlayer(p)

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    您必须设置该玩家的team,因为它是mappedBy 团队实体。

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

    或更改以下

     Player p = new Player();
     p.setTeam(team);    // here is the change 
     team.addPlayer(p);
    

    【讨论】:

    • 这是因为在 JPA 世界中,关系的所有者负责设置映射键。您确实通过设置 mappedBy 属性将关系的所有者指定为 Player。是的,我知道,它的定义与关系映射完全相反。
    • 我没有设置任何东西mappedBy。 OP 做到了,但他没有通过设置 team 来设置 Player 的父级
    • 我看到有人使用 EntityMenager.persist( ) 而不是 Session.save ( ) 的教程,我的方式很有效。嗯..
    • 是的,对不起。我正在评论您的回答,因为我同意它并且只想说明为什么必须像您一样完成它:)。评论中的“你”实际上是指问题的作者。抱歉误导。我不能再编辑评论了:(。
    • @Bambelal,当对象为Detached时,persist 会给出异常
    【解决方案2】:

    如果有双向关系,则必须始终设置关系的两端。

    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); 
            }  
    

    另外,您必须在映射中提供 Cascade Type。

    @OneToMany(mappedBy = "team",cascade = CascadeType.PERSIST)
    private List<Player> players = new ArrayList<>();
    

    【讨论】:

    • 在我上面链接的教程中,没有人使用关系的两端。
    【解决方案3】:

    教程中的人从不设置关系的两端,他们的代码工作正常(例如https://www.youtube.com/watch?v=jAi8bY-H_ek):)

    当我使用 player.setTeam(team) 而不是 team.addPlayer(player) 时,它可以工作(列不是 NULL)..

    【讨论】:

      猜你喜欢
      • 2013-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-20
      • 2021-06-16
      • 2016-07-02
      • 2020-04-15
      • 1970-01-01
      相关资源
      最近更新 更多