Как реализовать двойную связь между объектами с помощью hibernate 6.5JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как реализовать двойную связь между объектами с помощью hibernate 6.5

Сообщение Anonymous »

У меня есть база данных, в которой две таблицы имеют двойную связь:
График базы данных
Спот может быть родительским для нескольких SpotConditions, поэтому существует базовая связь OneToMany. .
Но кроме того, каждый Spot должен сохранять текущее SpotCondition, это делается с помощью «spt_current_condition» в качестве внешнего ключа.
Я работаю с Spring Boot (затем в Hibernate в фон), и цель состоит в том, чтобы иметь двунаправленную связь между Spot и текущим SpotCondition.
Мне удалось заставить его работать с Spring Boot 2.7.1 (Hibernate 5), но Я перешел на Spring Boot 3 (Hibernate 6.5), и теперь у меня есть java.lang.StackOverflowError: null при попытке получить Spot со встроенным CurrentSpotCondition (и в это SpotCondition также должно быть встроено Spot ).
Здесь возникает зацикленная ситуация, и я думаю, что это основа проблемы. Я не понимаю, почему это работало раньше, а не сейчас. Буду признателен за любой вклад, который подскажет мне идею :-)
Большое спасибо за вашу помощь.
Это мои 2 объекты:

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

@Entity
@Table( name = "t_spot_spt" )
@Data
@NoArgsConstructor
public class Spot {

@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "spt_id" )
private Integer             id;

@OneToOne( fetch = FetchType.EAGER )
@JoinColumn( name = "spt_current_condition" )
private SpotCondition       currentCondition;

@OneToMany( mappedBy = "spot", fetch = FetchType.LAZY )
private List conditions;

@Column( name = "spt_bla_id" )
private Integer             bladeId;

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

@Entity
@Table( name = "t_spot_condition_scd" )
@Data
@NoArgsConstructor
@ToString( onlyExplicitlyIncluded = true )
public abstract class SpotCondition implements Diffable {

@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "scd_id" )
@ToString.Include
protected Integer                       id;

@ManyToOne( fetch = FetchType.EAGER )
@JoinColumn( name = "scd_spt_id" )
protected Spot                          spot;
Я не уверен, что это правильный способ сопоставления, но для меня это логично.
Это классы, которые я использую для получения данных
Репозиторий:

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

public interface SpotRepository extends JpaRepository {

List findByBladeId( Integer bladeId );

Сервис:

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

    @Override
@Transactional( readOnly = true )
public Integer findWorstDamageSeverityIdByBlade( Integer bladeId ) {
short level = Short.MIN_VALUE;
Integer sevId = null;
boolean repairPresent = false;
for ( Spot spt : spotRepository.findByBladeId( bladeId ) ) {
SpotCondition sc = spt.getCurrentCondition();
//DO SOME STUFF
...

Это начало трассировки стека:

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

2024-07-25T21:09:55.332+02:00[0;39m [31mERROR[0;39m [35m19556[0;39m [2m---[0;39m [2m[p-nio-80-exec-6][0;39m [2m[0;39m[36mo.a.c.c.C.[.[.[.[dispatcherServlet]     [0;39m [2m:[0;39m Servlet.service() for servlet [dispatcherServlet] in context with path [/bladeexpert] threw exception [Handler dispatch failed: java.lang.StackOverflowError] with root cause

java.lang.StackOverflowError:  null
at org.hibernate.sql.results.internal.NavigablePathMapToInitializer.get(NavigablePathMapToInitializer.java:33) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:138) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:123) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.collection.internal.CollectionFetch.createAssembler(CollectionFetch.java:88) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetch.createAssembler(DelayedCollectionFetch.java:50) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.(AbstractEntityInitializer.java:205) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityJoinedFetchInitializer.(EntityJoinedFetchInitializer.java:48) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:171) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:157) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:36) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:150) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:123) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createAssembler(EntityFetchJoinedImpl.java:145) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.(AbstractEntityInitializer.java:205) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityJoinedFetchInitializer.(EntityJoinedFetchInitializer.java:48) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:171) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:157) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:36) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:150) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:123) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createAssembler(EntityFetchJoinedImpl.java:145) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.(AbstractEntityInitializer.java:205) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityJoinedFetchInitializer.(EntityJoinedFetchInitializer.java:48) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:171) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:157) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createInitializer(EntityFetchJoinedImpl.java:36) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:150) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:123) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl.createAssembler(EntityFetchJoinedImpl.java:145)  ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.(AbstractEntityInitializer.java:205) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityResultInitializer.(EntityResultInitializer.java:34) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityResultImpl.createInitializer(EntityResultImpl.java:106) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityResultImpl.createInitializer(EntityResultImpl.java:95) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityResultImpl.createInitializer(EntityResultImpl.java:30) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:150) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper$1.resolveInitializer(ResultsHelper.java:123) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntityResultImpl.createResultAssembler(EntityResultImpl.java:86) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.jdbc.internal.StandardJdbcValuesMapping.resolveAssemblers(StandardJdbcValuesMapping.java:53) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper.createRowReader(ResultsHelper.java:80) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.ResultsHelper.createRowReader(ResultsHelper.java:65) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:188) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:83) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:76) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:65) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.loader.ast.internal.SingleUniqueKeyEntityLoaderStandard.load(SingleUniqueKeyEntityLoaderStandard.java:127) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:2645) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:2637) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchByUniqueKeyInitializer.initializeInstance(EntitySelectFetchByUniqueKeyInitializer.java:96) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.InitializersList.initializeInstance(InitializersList.java:73) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
at org.hibernate.sql.results.internal.StandardRowReader.coordinateInitializers(StandardRowReader.java:113) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
Я пытался изменить поведение сопоставления OneToOne на LAZY вместо EAGER.

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

@Entity
@Table( name = "t_spot_spt" )
@Data
@NoArgsConstructor
public class Spot {

@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "spt_id" )
private Integer             id;

@OneToOne( fetch = FetchType.LAZY ) //CHANGED FROM EAGER TO LAZY
@JoinColumn( name = "spt_current_condition" )
private SpotCondition       currentCondition;

@OneToMany( mappedBy = "spot", fetch = FetchType.LAZY )
private List conditions;

@Column( name = "spt_bla_id" )
private Integer             bladeId;
Это сработало, но когда я пытаюсь получить CurrentSpotCondition из Spot, у меня появляется предупреждающее сообщение: [2m2024-07-25T21:30:11.878+02:00[0; 39м [33м WARN[0;39м [35м19556[0;39м] [2м---[0;39м [2м[p-nio-80-exec-3][0;39м [2м[0;39м[36мес.х.э.и. StatefulPersistenceContext [0;39m [2m:[0;39m HHH000179: Сужение прокси до класса com.bladeexpert.core.entity.spot.damage.OutdoorDamageSpotCondition — эта операция прерывается ==
И, наконец, CurrentSpotContition не получен.

Подробнее здесь: https://stackoverflow.com/questions/787 ... ernate-6-5
Ответить

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

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

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

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

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