Как сохранить объекты в отношениях @ManyToMany с помощью @EmbeddedIdJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как сохранить объекты в отношениях @ManyToMany с помощью @EmbeddedId

Сообщение Anonymous »

Я использую Spring Boot 3. У меня есть 2 объекта в отношениях @ManyToMany: Встреча (имя таблицы — «встреча») и Документ (имя таблицы — «документ»), таблица отношений — «relation_document_meeting». Что я хочу сделать, так это то, что когда я сохраняю новое собрание и связанный с ним новый документ (оба из них не имеют идентификатора), Hibernate создаст 2 новые записи: 1 в «встрече» и 1 в «документе», а также новая запись в «relation_document_meeting». Ниже приведены мои сущности:
Собрание сущности:

Код: Выделить всё

@Data
@Entity
@NoArgsConstructor
@Table(name = "meeting")
@Accessors(chain = true)
@SuppressWarnings("common-java:DuplicatedBlocks")
public class Meeting extends AbstractAuditingEntity implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
@Column(name = "id")
private Long id;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "meeting", orphanRemoval = true)
private List documents = new ArrayList();

public void addDocument(Document document, boolean isMain) {
if (this.documents.stream().noneMatch(relDocument -> relDocument.getDocument().equals(document))) {
RelDocumentMeeting relDocumentMeeting = new RelDocumentMeeting(document, this, isMain);
documents.add(relDocumentMeeting);
document.getMeetings().add(relDocumentMeeting);
}
}
Документ сущности:

Код: Выделить всё

@Data
@Entity
@NoArgsConstructor
@Table(name = "document")
@Accessors(chain = true)
@SuppressWarnings("common-java:DuplicatedBlocks")
public class Document implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
@Column(name = "id")
private Long id;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "document", orphanRemoval = true)
private List meetings = new ArrayList();
Сущность RelDocumentMeeting (субъект связи)

Код: Выделить всё

@Data
@Entity
@NoArgsConstructor
@Accessors(chain = true)
@Table(name = "relation_document_meeting")
public class RelDocumentMeeting extends AbstractAuditingEntity  implements Serializable {

@EmbeddedId
private RelDocumentMeetingId id;

@ManyToOne
@MapsId("documentId")
private Document document;

@ManyToOne
@MapsId("meetingId")
private Meeting meeting;

@Column(name = "main")
private boolean main = false;
Встроенный идентификатор

Код: Выделить всё

@Data
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class RelDocumentMeetingId implements Serializable {

@Column(name = "document_id", nullable = false)
private Long documentId;

@Column(name = "meeting_id", nullable = false)
private Long meetingId;
Теперь, когда я сохраняю пару новых собраний и документов (оба не имеют идентификатора), выдается ошибка

Код: Выделить всё

org.springframework.orm.jpa.JpaSystemException: Could not set value of type [org.hibernate.id.IdentifierGeneratorHelper$1]: 'com.domain.RelDocumentMeetingId.meetingId' (setter)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:341)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:241)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:335)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220)
Caused by: org.hibernate.PropertyAccessException: Could not set value of type [org.hibernate.id.IdentifierGeneratorHelper$1]:  ' c o m . k d . s m a . d o m a i n . R e l D o c u m e n t M e e t i n g I d . m e e t i n g I d '   ( s e t t e r ) < b r   / >         a t   o r g . h i b e r n a t e . p r o p e r t y . a c c e s s . s p i . S e t t e r F i e l d I m p l . s e t ( S e t t e r F i e l d I m p l . j a v a : 8 8 ) < b r   / >         a t   o r g . h i b e r n a t e . i d . C o m p o s i t e N e s t e d G e n e r a t e d V a l u e G e n e r a t o r . g e n e r a t e ( C o m p o s i t e N e s t e d G e n e r a t e d V a l u e G e n e r a t o r . j a v a : 1 4 0 ) < b r   / >         a t   o r g . h i b e r n a t e . i d . I d e n t i f i e r G e n e r a t o r . g e n e r a t e ( I d e n t i f i e r G e n e r a t o r . j a v a : 1 4 7 ) < b r   / >         a t   o r g . h i b e r n a t e . e v e n t . i n t e r n a l . A b s t r a c t S a v e E v e n t L i s t e n e r . g e n e r a t e I d ( A b s t r a c t S a v eEventListener.java:153)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:124)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:175)
at org.hibernate.event.internal.DefaultPersistEventListener.persist(DefaultPersistEventListener.java:93)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:77)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:138)
at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:818)
at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:333)
at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:323)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:517)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:439)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:224)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:551)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:481)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:442)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:224)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:157)
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:161)
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:144)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:79)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:52)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1366)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.lambda$new$2(ConcreteSqmSelectQueryPlan.java:136)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:362)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:303)
at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:509)
at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:427)
at org.hibernate.query.Query.getResultList(Query.java:120)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$ExistsExecution.doExecute(JpaQueryExecution.java:315)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:92)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:149)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:137)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:392)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
...  60 common frames omitted
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Long field com.domain.RelDocumentMeetingId.meetingId to org.hibernate.id.IdentifierGeneratorHelper$1
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
at java.base/java.lang.reflect.Field.set(Field.java:799)
at org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:57)
... 107 common frames omitted
Как добавить встречу

Код: Выделить всё

Meeting meeting = new Meeting();
Document document = new Document();
meeting.addDocument(document, true);
meetingRepository.save(meeting);
Можно ли это как-то сделать? Или мне нужно сначала сохранить одну сторону отношений?

Подробнее здесь: https://stackoverflow.com/questions/792 ... embeddedid
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»