У меня есть отношение «многие ко многим» в моем проекте, и хотя я могу писать в своей таблице двух сущностей, в реляционной таблице ничего не записывается.

Вот как я объявляю это с помощью аннотаций 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);
    }
}
3
Felipe Mosso 27 Фев 2015 в 04:08

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 для повышения производительности, потому что это может привести к загрузке очень большого набора данных.

14
naXa 11 Июн 2015 в 08:06

...

Обычно 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();
0
kafkas 24 Апр 2020 в 21:28

Нет необходимости устанавливать отношение «многие ко многим» для обеих сущностей.

Просто удали session.setFlushMode(FlushMode.MANUAL);

По умолчанию HibernateTemplate внутри Spring установлен FlushMode.MANUAL

Это исходный код из HibernateTemplate.

 if (session == null) {
            session = this.sessionFactory.openSession();
            session.setFlushMode(FlushMode.MANUAL);
            isNew = true;
        }
0
Vahe Gharibyan 24 Ноя 2018 в 20:37

У меня такая же проблема. Я поменял местами, где полное сопоставление объявляет класс, для которого мы будем использовать функцию 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
Kien Ngo 11 Окт 2015 в 11:22