У меня есть отношение «многие ко многим» в моем проекте, и хотя я могу писать в своей таблице двух сущностей, в реляционной таблице ничего не записывается.
Вот как я объявляю это с помощью аннотаций 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);
...
}
В этом случае учтите, что у меня уже есть запись с идентификатором «1» для профессора.
Как я уже сказал, он записывает в таблицу Aluno и Professor, но НЕ записывает ничего в таблицу ALUNO_PROFESSOR.
Я уже рассмотрел эти три типа похожих вопросов, но ни один из них мне не помог:
Hibernate и Spring: значение многие-ко-многим не вставлено в сгенерированную таблицу
JPA "многие ко многим" продолжают присоединяться к столу
Как сохранить отношение @ManyToMany - повторяющаяся запись или отдельный объект
ИЗМЕНИТЬ - Добавление дополнительных фрагментов кода
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);
}
}
4 ответа
Попробуй это:
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
для повышения производительности, потому что это может привести к загрузке очень большого набора данных.
...
Обычно Hibernate сохраняет постоянное состояние в памяти. Процесс синхронизации этого состояния с базовой БД называется сбросом.
Когда мы используем метод save (), данные, связанные с операцией сохранения, не будут сброшены в БД до тех пор, пока не будет сделан явный вызов метода flush () или commit ().
Если мы используем реализации JPA, такие как Hibernate, тогда эта конкретная реализация будет управлять операциями сброса и фиксации.
Здесь мы должны помнить о том, что, если мы решим сбросить данные самостоятельно, не фиксируя их, изменения не будут видны внешней транзакции, если в этой транзакции или на уровне изоляции не будет выполнен вызов фиксации. внешней транзакции READ_UNCOMMITTED.
...
Из разницы между save () и saveAndFlush () в Spring Data JPA от baeldung: https://www.baeldung.com/spring-data-jpa-save- сохранить и промыть
employeeRepository.saveAndFlush(new Employee(2L, "Alice"));
Или
employeeRepository.save(new Employee(2L, "Alice"));
employeeRepository.flush();
Нет необходимости устанавливать отношение «многие ко многим» для обеих сущностей.
Просто удали session.setFlushMode(FlushMode.MANUAL);
По умолчанию HibernateTemplate внутри Spring установлен FlushMode.MANUAL
Это исходный код из HibernateTemplate
.
if (session == null) {
session = this.sessionFactory.openSession();
session.setFlushMode(FlushMode.MANUAL);
isNew = true;
}
У меня такая же проблема. Я поменял местами, где полное сопоставление объявляет класс, для которого мы будем использовать функцию 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;
}
И он работал нормально.
Похожие вопросы
Связанные вопросы
Новые вопросы
mysql
MySQL — это бесплатная система управления реляционными базами данных (RDBMS) с открытым исходным кодом, которая использует язык структурированных запросов (SQL). НЕ ИСПОЛЬЗУЙТЕ этот тег для других БД, таких как SQL Server, SQLite и т. д. Это разные БД, которые используют свои собственные диалекты SQL для управления данными.