我的项目中有多对多的关系,虽然我能够在我的两个实体表中编写,但关系表却没有写入任何内容。
以下是我如何使用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);
}
}
答案 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()。如果不这样做,则不会插入该值。