У меня 2 класса:
@Entity
@Table(name = "TableA")
public class EntityA
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private final Integer id = null;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "BId")
private EntityB b;
public EntityA(EntityB b)
{
this.b = b;
}
}
@Entity
@Table(name = "TableB")
public class EntityB
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private final Integer id = null;
@OneToOne(mappedBy = "b")
private final EntityA a = null;
}
Когда я делаю
session.save(new EntityA(new EntityB());
база данных только вставляет запись в TableA и оставляет столбец, который ссылается на TableB как NULL
Если я сначала вставлю b, затем a, он будет работать, но он должен работать и с одним вызовом.
В других вопросах / ответах упоминается, что аннотации неверны, но я не вижу разницы между моим и предоставленными решениями.
Я также попытался добавить CascadeType.PERSIST в обе аннотации @OneToOne, но это тоже не сработало.
при текущей настройке ошибок нет, просто нет записей для TableB, раньше у меня для столбца в SQLServer было установлено значение NOT NULL, а затем я получил ошибки вставки, говоря, что я не могу вставить значения NULL для BId
Ах, я вижу, мне пришлось использовать CascadeType.ALL вместо ... на самом деле любую комбинацию других, со ВСЕМ на @OneToOne, это сработало
@Wietlol это потому, что вы не используете entityManager JPA для сохранения, а вместо этого используете сеанс Hibernate, поэтому вам нужно либо использовать Hibernate org.hibernate.annotations.CascadeType.SAVE_UPDATE, либо, если вы используете JPA @CascadeType, если вы используете ВСЕ, он также будет охватывать каскады Hibernate. Посмотрите здесь и здесь для получения дополнительной информации.
Кажется, это ответ, не могли бы вы дать его в качестве ответа, чтобы я мог отметить его как решение? Кроме того, было бы лучше использовать диспетчер сущностей вместо сеанса гибернации? Я как бы пошел в это с помощью «Это просто должно работать», поэтому я могу выбрать использование чего-то другого, кроме спящего режима, если это уменьшит сложность или ошибки в настройке.
@Wietlol Да, лучше придерживаться одного: JPA или Hibernate. Если что-то невозможно с JPA, я не вижу причин использовать сеанс Hibernate. Мой совет: попробуйте использовать JPA для всех ваших нужд. Если что-то невозможно через JPA, вы всегда можете получить сеанс через Session session = em.unwrap(Session.class);.
Просто убедитесь, что вы используете полностью определенные имена для Hibernate в своем коде для аннотаций и классов Hibernate, чтобы, взглянув на код, вы знали, что отклоняется от JPA (поскольку существует много классов с одинаковыми именами в JPA и пространстве имен Hibernate) . Пример: org.hibernate.Query query = session.createQuery(queryString)




В jpa параметр Cascade по умолчанию - NONE ... поэтому объекты в отношениях (B в вашем случае) по умолчанию не вставляются (сохраняются) ... Вам необходимо аннотировать отношения с помощью @OneToOne (fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
Проблема, с которой я столкнулся, заключалась в том, что даже с PERSIST он все еще не работал. поскольку cascase может принимать список типов, я пробовал добавлять все больше и больше, но ТОЛЬКО с CascaseTyoe.ALL он работал, больше ничего
Прежде всего, вы должны удалить последнее ключевое слово из ваших объектов. Попробуй это:
@Entity
@Table(name = "TableA")
class EntityA {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private Integer id;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name = "BId")
private EntityB b;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityB getB() {
return b;
}
public void setB(EntityB b) {
this.b = b;
}
public EntityA(EntityB b) {
this.b = b;
b.setA(this);
}
}
@Entity
@Table(name = "TableB")
class EntityB {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private Integer id;
@OneToOne(mappedBy = "b")
private EntityA a;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityA getA() {
return a;
}
public void setA(EntityA a) {
this.a = a;
}
}
Я использую базу данных Spring boot, hibernate и H2
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext app = SpringApplication.run(DemoApplication.class, args);
ServiceCascade bean = app.getBean(ServiceCascade.class);
bean.save();
}
}
@Service
class ServiceCascade {
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void save() {
EntityA entityA = new EntityA(new EntityB());
entityManager.persist(entityA);
}
}
Следующие журналы показывают, что два объекта вставлены правильно.
org.hibernate.SQL : insert into tableb (id) values (null)
org.hibernate.SQL : insert into tablea (id, bid) values (null, ?)
o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [1]
Это не сработало, как я уже упоминал, я уже пытался добавить CascadeType.PERSIST к обеим сторонам. CascadeType.ALL, похоже, работает, и @Cascade из org.hibernate.annotation (как упоминал Ранджит) также работает.
Я использую Session :: save из спящего режима, у меня работает менеджер сущностей
Какие ошибки возникают с аннотациями CascadeType и без них?