JPA很多关系没有插入到生成的表中

时间:2015-02-27 01:08:47

标签: mysql spring hibernate jpa many-to-many

我的项目中有多对多的关系,虽然我能够在我的两个实体表中编写,但关系表却没有写入任何内容。

以下是我如何使用JPA注释声明这一点:

Professor.java

@Entity
@Table(name = "Professor")
public class Professor implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "idProfessor", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "ALUNO_PROFESSOR",
            joinColumns = @JoinColumn(name = "idProfessor", referencedColumnName = "idProfessor"),
            inverseJoinColumns = @JoinColumn(name = "idAluno", referencedColumnName = "idAluno"))
    private List<Aluno> alunoList;

    // getters and setters
}

Aluno.java

@Entity
@Table(name = "Aluno")
public class Aluno implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "idAluno", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToMany(mappedBy = "alunoList", fetch = FetchType.EAGER)
    private List<Professor> professorList;

    // getters and setters
}

这是要插入数据库的服务层:

@Autowired
private AlunoDao alunoDao;

@Autowired
private ProfessorDao professorDao;

@RequestMapping(value = RestUriConstants.SUBMETER, method = RequestMethod.POST)
public @ResponseBody JsonResponse submeter(@RequestBody final Aluno aluno) {

    Professor professor = professorDao.find(1);
    aluno.setProfessorList(Arrays.asList(professor));
    alunoDao.persist(aluno);

    ...
}

在这种情况下,请考虑我已经有一个ID为&#34; 1&#34;教授。

正如我所说,它确实写在Aluno和教授表上,但不会在ALUNO_PROFESSOR表中写任何内容。

我已经看过这三种类似的问题,但没有一个可以帮助我:

Hibernate and Spring: value of many-to-many not inserted into generated table

JPA many-to-many persist to join table

How to persist @ManyToMany relation - duplicate entry or detached entity

编辑 - 添加更多代码段

JpaAlunoDao.java

@Repository
public class JpaAlunoDao implements AlunoDao {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public void persist(Aluno aluno) {
        em.persist(aluno);
    }
}

JpaExercicioDao.java

@Repository
public class JpaExercicioDao implements ExercicioDao {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public void persist(Exercicio exercicio) {
        em.persist(exercicio);
    }
}

5 个答案:

答案 0 :(得分:10)

试试这个:

public class Professor {
  @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
  @JoinTable(name = "ALUNO_PROFESSOR",
        joinColumns = @JoinColumn(name = "idProfessor", referencedColumnName = "idProfessor"),
        inverseJoinColumns = @JoinColumn(name = "idAluno", referencedColumnName = "idAluno"))
  private List<Aluno> alunoList;
}

public class Aluno {
  @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
  @JoinTable(name = "ALUNO_PROFESSOR",
        joinColumns = @JoinColumn(name = "idAluno", referencedColumnName = "idAluno"),
        inverseJoinColumns = @JoinColumn(name = "idProfessor", referencedColumnName = "idProfessor"))
  private List<Professor> professorList;
}

这将确保两个实体上的多对多关系的元数据可用,并且关系任一侧的操作都级联到另一方。

我还建议将FetchType.EAGER替换为FetchType.LAZY以获得更好的性能,因为这有可能加载非常大的数据集。

答案 1 :(得分:2)

我有同样的问题。我将完整映射声明的地址交换到我们将使用save()函数的类。 在你的情况下:

public class Aluno {
  @ManyToMany(fetch = FetchType.EAGER)
  @JoinTable(name = "ALUNO_PROFESSOR",
        joinColumns = @JoinColumn(name = "idAluno"),
        inverseJoinColumns = @JoinColumn(name = "idProfessor")
  private List<Professor> professorList;
}

public class Professor {
  @ManyToMany(fetch = FetchType.EAGER, mappedBy = "professorList",)  
  private List<Aluno> alunoList;
}

并且工作正常。

答案 2 :(得分:0)

两个实体都不必设置多对多关系。

只需删除session.setFlushMode(FlushMode.MANUAL);

默认情况下,Spring集合FlushMode.MANUAL中的HibernateTemplate

这是来自HibernateTemplate的源代码。

 if (session == null) {
            session = this.sessionFactory.openSession();
            session.setFlushMode(FlushMode.MANUAL);
            isNew = true;
        }

答案 3 :(得分:0)

...

通常,Hibernate将持久状态保存在内存中。将此状态同步到基础数据库的过程称为刷新。

当我们使用save()方法时,除非并且直到对flush()或commit()方法进行显式调用,否则与保存操作关联的数据将不会刷新到DB。

如果我们使用Hibernate之类的JPA实现,则该特定实现将管理刷新和提交操作。

我们在这里要记住的一件事是,如果我们决定不提交而自行刷新数据,那么外部事务将看不到更改,除非在此事务中进行了提交调用或外部事务的隔离级别为READ_UNCOMMITTED。

...

来自baeldung的Spring Data JPA中save()和saveAndFlush()之间的区别: https://www.baeldung.com/spring-data-jpa-save-saveandflush

employeeRepository.saveAndFlush(new Employee(2L, "Alice"));

  employeeRepository.save(new Employee(2L, "Alice"));
  employeeRepository.flush();

答案 4 :(得分:0)

有时问题在于您插入值的方式。我举例说明。

User user = userFacade.find(1);      
Post post = new Post("PRUEBA");
user.addPostCollection(post);
post.addUserCollection(user);
postFacade.create(post);

您必须在 postCollection 中添加帖子,在 userCollection 中添加用户。你有两个在两个实体的集合中添加对应的实体。

类用户

  public void addPostCollection(Post post) {
    if(postCollection == null){
        postCollection = new ArrayList<Post>();
    }
    postCollection.add(post);
}

@ManyToMany(mappedBy = "userCollection")
private Collection<Post> postCollection;

班级帖子

    public void addUserCollection(User user){
        if(userCollection == null){
            userCollection = new ArrayList<User>();
        }
        userCollection.add(user);
    }

 @JoinTable(name = "USER_POST_R", joinColumns = {
 @JoinColumn(name = "POSTID", referencedColumnName = "ID")}, inverseJoinColumns = {
 @JoinColumn(name = "USERID", referencedColumnName = "ID")})
    @ManyToMany
    private Collection<User> userCollection;

此外,实例化列表也很重要,例如 userCollection = new ArrayList()。如果不这样做,则不会插入该值。