Spring Data JPA implementing Persistable results in InvalidDataAccessApiUsageException: detached entity passed to persist

huangapple go评论74阅读模式
英文:

Spring Data JPA implementing Persistable results in InvalidDataAccessApiUsageException: detached entity passed to persist

问题

I'm trying to implement Persistable to delegate entity state detection to the interface and to finally minimize the number of db queries while saving / updating entities. After implementing I get InvalidDataAccessApiUsageException: detached entity passed to persist while trying to update existing entities.

这是我尝试实现Persistable接口,以将实体状态检测委托给接口,并最终在保存/更新实体时减少数据库查询次数。但在实现后,当尝试更新现有实体时,我收到了InvalidDataAccessApiUsageException: detached entity passed to persist异常。

These exceptions occur for every class while using the Spring Data Repository save method. Code is working fine without Persistable but with a lot of more queries.

这些异常会在使用Spring Data Repository的save方法时发生,对于每个类都会发生。如果不使用Persistable接口,代码运行正常,但会产生更多的查询。

Overall the case is to get rid of many queries generated while using Spring Data JPA save method. Without implementation, all methods are working Ok.

总的来说,问题是要消除在使用Spring Data JPA save方法时生成的许多查询。如果不实现Persistable接口,所有方法都正常工作。

Anybody has any idea on what's going on here?

有人对这里发生的情况有什么想法吗?

Implementation of Persistable according to the docs.

根据文档的要求实现了Persistable接口。

Example entity class

示例实体类

Service class

服务类

Repository

仓库

Test case

测试用例

Error

错误

英文:

I'm trying to implement Persistable to delegate entity state detection to the interface and to finally minimize the number of db queries while saving / updating entities. After implementing I get InvalidDataAccessApiUsageException: detached entity passed to persist while trying to update existing entities.

These exceptions occur for every class while using the Spring Data Repository save method. Code is working fine without Persistable but with a lot of more queries.

Overall the case is to get rid of many queries generated while using Spring Data JPA save method. Without implementation, all methods are working Ok.

This is Persistable implementation for a superClass based on the Spring Data JPA docs

Anybody has any idea on what's going on here?

Implementation of Persistable according to the docs.

@MappedSuperclass
public class BaseEntity implements Persistable<UUID> {


    public BaseEntity () {

    }

    public BaseEntity(UUID id, Long version, Timestamp createdDate, Timestamp lastModifiedDate) {
        this.id = id;
        this.version = version;
        this.createdDate = createdDate;
        this.lastModifiedDate = lastModifiedDate;
    }

    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(
            name = "UUID",
            strategy = "org.hibernate.id.UUIDGenerator")
    @Column(updatable = false, nullable = false )
    private UUID id;

    @Version
    private Long version;

    @CreationTimestamp
    @Column(updatable = false, nullable = false)
    private Timestamp createdDate;

    @UpdateTimestamp
    private Timestamp lastModifiedDate;

    public int hashCode () {
        return Objects.hash(this.id);
    }

    public boolean equals (Object that) {
        return this == that || that instanceof BaseEntity && Objects.equals(this.id, ((BaseEntity) that).id);
    }

    public UUID getId() {
        return id;
    }

    @Transient
    private boolean isNew = true;

    @Override
    public boolean isNew() {
        return isNew;
    }

    @PrePersist
    @PostLoad
    void markNotNew() {
        this.isNew = false;
    }

    public void setId(UUID id) {
        this.id = id;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public Timestamp getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Timestamp createdDate) {
        this.createdDate = createdDate;
    }

    public Timestamp getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(Timestamp lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }
}

Example entity class

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Question extends BaseEntity {

    private String contents;
    private String mainTech;
    private String specificTech;
    @Enumerated(EnumType.STRING)
    private SkillLevel skillLevel;
    @OneToMany(mappedBy = "question", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    private List<Answer> answers = new ArrayList<>();

    @Builder
    public Question(UUID id,
                    Long version,
                    Timestamp createdDate,
                    Timestamp lastModifiedDate,
                    java.lang.String contents,
                    String mainTech,
                    java.lang.String specificTech,
                    ArrayList<Answer> answers,
                    SkillLevel skillLevel) {
        super(id, version, createdDate, lastModifiedDate);
        this.contents = contents;
        this.mainTech = mainTech;
        this.specificTech = specificTech;
        this.answers = answers;
        this.skillLevel = skillLevel;
    }

    public void addAnswer(Answer answer) {
        this.getAnswers().add(answer);
        answer.setQuestion(this);
    }

    public void removeAnswer(Answer answer) {
        this.getAnswers().remove(answer);
        answer.setQuestion(null);
    }

    @Override
    public java.lang.String toString() {
        return "Question{" +
                "id='" + this.getId() + '\'' +
                "contents='" + contents + '\'' +
                ", mainTech=" + mainTech +
                ", specificTech='" + specificTech + '\'' +
                ", skillLevel=" + skillLevel +
                ", answers=" + answers.size() +
                '}';
    }
}

Service class

@Service
public class QuestionServiceImpl implements QuestionService {

    private final QuestionRepository questionRepository;
    private final QuestionMapper mapper;
    private final EntityManagerFactory emf;

    public QuestionServiceImpl(
            QuestionRepository questionRepository,
            EntityManagerFactory emf,
            QuestionMapper mapper
    ) {
        this.questionRepository = questionRepository;
        this.mapper = mapper;
        this.emf = emf;
    }

    @Override
    public QuestionDto saveOrUpdate(QuestionDto questionDto) {
        Question save = questionRepository.save(mapper.dtoToObject(questionDto, contextProvider()));
        return mapper.objectToDto(save, contextProvider());
    }


    public QuestionDto findByUuId(UUID uuid) {
        Question question = emf.createEntityManager().createQuery("select q from Question q " +
                "left join fetch q.answers " +
                "where q.id = :uuid", Question.class)
                .setParameter("uuid", uuid)
                .getSingleResult();
        return mapper.objectToDto(question, contextProvider());
    }

//More code ...
}

Repository

@Repository
public interface QuestionRepository extends JpaRepository<Question, UUID> {

    @Override
    List<Question> findAll();

    @Override
    <S extends Question> S save(S s);

    @Override
    Optional<Question> findById(UUID uuid);

    Question findByContentsEquals(String contents);

    List<Question> findAllByMainTechAndSpecificTech(String mainTech, java.lang.String specificTech);

    List<Question> findAllByMainTech(String mainTech);

    List<Question> findAllByMainTechAndSkillLevel(String mainTech, SkillLevel skillLevel);

    List<Question> findAllByMainTechAndSkillLevelAndSpecificTech(String mainTech, SkillLevel skillLevel, String specificTech);

}

Test case

@RunWith(SpringRunner.class)
@SpringBootTest
class QuestionServiceImplTest {

    @Autowired
    QuestionRepository repository;

    @Autowired
    QuestionServiceImpl service;

    @Autowired
    QuestionMapper mapper;


    QuestionDto question1;
    QuestionDto question2;

    @BeforeEach
    void setUp() {

        question1 = QuestionDto.builder()
                .answers(new ArrayList<>())
                .contents("testQuestion1")
                .skillLevel(SkillLevel.ENTRY)
                .specificTech("Core")
                .mainTech("Java")
                .build();

        question2 = QuestionDto.builder()
                .answers(new ArrayList<>())
                .contents("testQuestion1")
                .skillLevel(SkillLevel.ENTRY)
                .specificTech("Core")
                .mainTech("Java")
                .build();

        assertAll(
                () -> assertThat(question1.getContents()).isEqualTo(question2.getContents())
        );
    }

    @Test
    public void callingSaveOrUpdateMultipleTimesShouldAlwaysReturnSingleEntity() {
        // Given
        QuestionDto savedQuestion1 = service.saveOrUpdate(question1);
        System.out.println("first save 1" + savedQuestion1);
        QuestionDto savedQuestion2 = service.saveOrUpdate(question2);
        System.out.println("first save 2" + savedQuestion2);

        QuestionDto savedQuestion1a = service.saveOrUpdate(savedQuestion1);
        QuestionDto savedQuestion1b = service.saveOrUpdate(savedQuestion1a);
        QuestionDto savedQuestion1c = service.saveOrUpdate(savedQuestion1b);
        System.out.println("last save 1");
        QuestionDto savedQuestion2a = service.saveOrUpdate(savedQuestion2);
        QuestionDto savedQuestion2b = service.saveOrUpdate(savedQuestion2a);
        service.saveOrUpdate(savedQuestion2b);
        System.out.println("last save 2");
        // When
        QuestionDto searchResult = service.findByUuId(savedQuestion1.getId());


        List<QuestionDto> all = service.findAll();
        // Then
        assertAll(
                () -> assertThat(searchResult).isNotNull(),
                () -> assertThat(searchResult.getId()).isEqualTo(savedQuestion1.getId()),
                () -> assertThat(all.size()).isEqualTo(2),
                () -> assertThat(all.get(0).getId()).isEqualTo(savedQuestion1.getId()),
                () -> assertThat(all.get(1).getId()).isEqualTo(savedQuestion2.getId())
        );
    }
}

Error

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.github.pawelbialas.testgeneratorapp.entity.question.model.Question; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.github.pawelbialas.testgeneratorapp.entity.question.model.Question
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:319)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy156.save(Unknown Source)
at com.github.pawelbialas.testgeneratorapp.entity.question.service.QuestionServiceImpl.saveOrUpdate(QuestionServiceImpl.java:38)
at com.github.pawelbialas.testgeneratorapp.entity.question.service.QuestionServiceImplTest.callingSaveOrUpdateMultipleTimesShouldAlwaysReturnSingleEntity(QuestionServiceImplTest.java:70)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.github.pawelbialas.testgeneratorapp.entity.question.model.Question
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:702)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:688)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314)
at com.sun.proxy.$Proxy139.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:554)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:371)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:204)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:657)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:621)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 72 more

答案1

得分: 3

为什么您觉得在示例代码上方的标题中已经标明是“用于具有手动分配标识符的实体的基类”,还需要对Persistable进行自定义定义,并加上带有@GeneratedValue注解的id呢?

以这种方式实现Persistable意味着无论何时通过从DTO进行映射来创建实体对象,Spring Data都会将其视为新对象。因此,JpaRepository.save()将在内部调用EntityManager.persist()。这意味着在测试中对QuestionDtoservice.saveOrUpdate(...)的所有后续调用(初始调用之后)将尝试持久化现有对象(而不是将其合并到上下文中),因此会出现错误。

如果您想要自定义的Persistable实现起作用,您需要拥有单独的saveupdate方法,其中update类似于以下内容:

questionRepository.findById(questionDto.getId())
.ifPresent(dbQuestionVersion -> 
    mapper.mapDtoOntoObject(questionDto, dbQuestionVersion, contextProvider()))

不过,我猜这可能不是您想要的解决方案。

英文:

Why do you feel you need a custom definition of Persistable with @GeneratedValue-annotated id when the caption above the sample code reads: 'A base class for entities with manually assigned identifiers'?

Implementing Persistable that way means that whenever you create the entity object by mapping from the DTO, it will be considered new by Spring Data. Consequently, JpaRepository.save() will call EntityManager.persist() internally. This implies all the subsequent calls to service.saveOrUpdate(...) on a QuestionDto in your test (after the initial one) will try to persist existing objects (instead of merging them into the context), hence the error.

If you want the custom Persistable implementation to work, you would need separate save and update methods where update looks sth like:

questionRepository.findById(questionDto.getId())
.ifPresent(dbQuestionVersion ->
mapper.mapDtoOntoObject(questionDto, dbQuestionVersion, contextProvider()))`

I'm guessing that's not what you want, though.

答案2

得分: 0

以下代码在BaseEntity中不可用。无论何时你使用OneToMany或ManyToOne,都应该在两个实体中声明。

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "foreign_key")
private Question question;
英文:

Below code not available in BaseEntiy. When ever you are OneToMany or ManyToOne you should declare in both entity

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "foreign_key")
private Question   question;

huangapple
  • 本文由 发表于 2020年8月23日 18:41:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63546000.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定