Spring Boot 对具有关联的多个实体使用自定义生成器@GenericGenerator

icnyk63a  于 2022-11-23  发布在  Spring
关注(0)|答案(1)|浏览(188)

我有两个Java类:
第一个类Class1如下所示:

@Entity
@Table(catalog = "mydb", schema = "dbo", name = "[myTable1]")
@Getter
@Setter
@Builder
@ToString(onlyExplicitlyIncluded = true)
@AllArgsConstructor
@NoArgsConstructor
public class Class1 {

    @Id
    @Column(name = "ID")
    @GeneratedValue(generator = "myGen")
    @GenericGenerator(name = "myGen",
            strategy = "Y.X.z.generator.MyGen")
    private Long id;

    @Column(name = "TEXT")
    private String text;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "ID")
    private Class2 class2;

第二个类Class2如下所示

@Entity
@Table(catalog = "mydb", schema = "dbo", name = "[myTable2]")
@Getter
@Setter
@Builder
@ToString(onlyExplicitlyIncluded = true)
@AllArgsConstructor
@NoArgsConstructor
public class Class2 {

    @Id
    @Column(name = "ID")
    @GeneratedValue(generator = "myGen")
    @GenericGenerator(name = "myGen",
            strategy = "de.svg.releasenotes.generator.MyGen")
    private Long id;

    @Column(name = "TEXT")
    private String text;

正如您所看到的,类1与类2之间存在ManyToOne关联。类1和类2使用相同的GenericGenerator(Y.X.z.generator.MyGen)。
发生器如下所示:

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;

import java.io.Serializable;
import java.util.stream.Stream;

public class MyGen implements IdentifierGenerator {

    @Override
    public Serializable generate(
            SharedSessionContractImplementor session, Object obj)
            throws HibernateException {

        String query = String.format("select %s from %s",
                session.getEntityPersister(obj.getClass().getName(), obj)
                        .getIdentifierPropertyName(),
                obj.getClass().getSimpleName());

        Stream<Long> ids = session.createQuery(query).stream();

        Long max = ids.max(Long::compare).orElse(0L);

        return max + 1;
    }

}

生成器make从DB.TableX中检索最大ID并将其递增1。
当我呼叫POST端点时,收到下列错误:

2022-11-15 15:27:26.214 ERROR 276510 --- [io-13778-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause

java.lang.StackOverflowError: null
    at org.apache.logging.slf4j.SLF4JLogger.isEnabledFor(SLF4JLogger.java:213) ~[log4j-to-slf4j-2.17.2.jar:2.17.2]
    at org.apache.logging.slf4j.SLF4JLogger.isEnabled(SLF4JLogger.java:121) ~[log4j-to-slf4j-2.17.2.jar:2.17.2]
    at org.apache.logging.log4j.spi.AbstractLogger.isEnabled(AbstractLogger.java:1513) ~[log4j-api-2.17.2.jar:2.17.2]
    at org.jboss.logging.Log4j2Logger.isEnabled(Log4j2Logger.java:46) ~[jboss-logging-3.4.3.Final.jar:3.4.3.Final]
    at org.jboss.logging.Logger.isTraceEnabled(Logger.java:98) ~[jboss-logging-3.4.3.Final.jar:3.4.3.Final]
    at org.jboss.logging.DelegatingBasicLogger.isTraceEnabled(DelegatingBasicLogger.java:54) ~[jboss-logging-3.4.3.Final.jar:3.4.3.Final]
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:86) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1372) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1452) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1649) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at  Y.X.z.generator.MyGen.generate(MyGen.java:25) ~[classes/:na]
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:115) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:801) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:341) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:510) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:434) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:153) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1372) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1452) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1649) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at  Y.X.z.generator.MyGen.generate(MyGen.java:25) ~[classes/:na]
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:115) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:801) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:341) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:510) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:434) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:153) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1372) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1452) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1649) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617) ~[hibernate-core-5.6.12.Final.jar:5.6.12.Final]

...
这表明MyGen有一个StackOverflowError。
有什么办法可以解决我的问题吗?
谢谢你,谢谢你

63lcw9qa

63lcw9qa1#

从堆栈跟踪看,似乎您可能在休眠中发现了一个bug,但很难分辨。
好消息是,如果我正确理解了您要做的事情,您就不需要自定义生成器,这意味着您应该能够解决您的问题。
您可以使用SEQUENCE生成策略为实体实现单调递增的id:
第一个

相关问题