Если у меня есть отношение @OneToMany с @Cascade (CascadeType.SAVE_UPDATE) следующим образом
public class One {
private Integer id;
private List<Many> manyList = new ArrayList<Many>();
@Id
@GeneratedValue
public Integer getId() {
return this.id;
}
@OneToMany
@JoinColumn(name="ONE_ID", updateable=false, nullable=false)
@Cascade(CascadeType.SAVE_UPDATE)
public List<Many> getManyList() {
return this.manyList;
}
}
И многие класс
public class Many {
private Integer id;
/**
* required no-arg constructor
*/
public Many() {}
public Many(Integer uniqueId) {
this.id = uniqueId
}
/**
* Without @GeneratedValue annotation
* Hibernate will use assigned Strategy
*/
@Id
public Integer getId() {
return this.id;
}
}
Если у меня есть следующий сценарий
One one = new One();
/**
* generateUniqueId method will Take care of assigning unique id for each Many instance
*/
one.getManyList().add(new Many(generateUniqueId()));
one.getManyList().add(new Many(generateUniqueId()));
one.getManyList().add(new Many(generateUniqueId()));
one.getManyList().add(new Many(generateUniqueId()));
И я звоню
sessionFactory.getCurrentSession().save(one);
Прежде чем продолжить
В соответствии с Переходное постоянство Справочная документация Hibernate, вы можете увидеть
Если родительский элемент передается для сохранения () , update () или saveOrUpdate (), все дочерние элементы передаются в saveOrUpdate ()
ок.Теперь давайте посмотрим, что такое Java Persistence с книгой Hibernate Рассказывает о методе saveOrUpdate
Hibernate запрашивает у таблицы MANY заданный идентификатор и , если он найден ,Hibernate обновляет строку . Если он не найден , требуется вставка новой строки .
Что может быть переведено в соответствии с
INSERT INTO ONE (ID) VALUES (?)
/**
* I have four Many instances added To One instance
* So four select-before-saving
*
* I DO NOT NEED select-before-saving
* Because i know i have a Fresh Transient instance
*/
SELECT * FROM MANY WHERE MANY.ID = ?
SELECT * FROM MANY WHERE MANY.ID = ?
SELECT * FROM MANY WHERE MANY.ID = ?
SELECT * FROM MANY WHERE MANY.ID = ?
INSERT INTO MANY (ID, ONE_ID) VALUES (?, ?)
INSERT INTO MANY (ID, ONE_ID) VALUES (?, ?)
INSERT INTO MANY (ID, ONE_ID) VALUES (?, ?)
INSERT INTO MANY (ID, ONE_ID) VALUES (?, ?)
Любой обходной путь, чтобы избежать выбора перед сохранением ???Да, вы можете либо
- Добавить столбец @Version (не применяется)
- Реализовать метод isTransient, предоставляемый перехватчиком Hibernate ( Опция, которую я имею )
Таким образом, чтобы избежать выбора по умолчанию перед сохранением поведения по умолчанию при использовании этого вида каскадирования, я улучшил свой код, назначив перехватчик Hibernate сеансу Hibernate Чья транзакция управляется Spring .
Вот мой репозиторий
До (без перехватчика Hibernate): Отлично работает!
@Repository
public class SomeEntityRepository extends AbstractRepository<SomeEntity, Integer> {
@Autowired
private SessionFactory sessionFactory;
@Override
public void add(SomeEntity instance) {
sessionFactory.getCurrentSession().save(instance);
}
}
После (с Hibernate Inteceptor): что-то идет не так (SQL-запрос не выполняется - ни INSERT, ни SELECT-BEFORE-SAVING)
@Repository
public class SomeEntityRepository extends AbstractRepository<SomeEntity, Integer> {
@Autowired
private SessionFactory sessionFactory;
@Override
public void add(SomeEntity instance) {
sessionFactory.openSession(new EmptyInterceptor() {
/**
* To avoid select-before-saving
*/
@Override
public Boolean isTransient(Object o) {
return true;
}
}).save(instance);
}
}
Мой вопрос: почему Springне сохраняется моя сущность и ее отношения при использовании Hibernate Interceptor, и что я должен сделать, чтобы работать нормально ???