首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >当父实体和子实体中存在同名属性时,“mappedBy引用未知的目标实体属性”

当父实体和子实体中存在同名属性时,“mappedBy引用未知的目标实体属性”
EN

Stack Overflow用户
提问于 2020-10-14 05:29:25
回答 2查看 674关注 0票数 0

我使用的是SpringBootV1.5.3,当我使用Hibernate继承时,当父实体和子实体中都有同名的属性时,就会发生AnnotationException: mappedBy reference an unknown target entity property

例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Apple => RedApple
      => GreenApple
      => etc.
Tree  => RedAppleTree
      => GreenAppleTree
      => etc.
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Tree.java

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@EqualsAndHashCode(exclude = {"apples"})
@DiscriminatorColumn(name = "colour")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Tree {
    @Id
    @GeneratedValue
    private Long id;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// RedAppleTree.java

@Entity
@Table(name = "tree")
@DiscriminatorValue("RED")
public class RedAppleTree extends Tree {
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "tree")
    private List<RedApple> apples;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Apple.java

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@DiscriminatorColumn(name = "colour")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Apple {
    @Id
    @GeneratedValue
    private Long id;

    @Enumerated(EnumType.STRING)
    @Column(insertable = false, updatable = false)
    private Colour colour;

    @JoinColumn(insertable = false, updatable = false)
    @ManyToOne
    private Tree tree;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// RedApple.java

@Entity
@Table(name = "apple")
@DiscriminatorValue("RED")
public class RedApple extends Apple {
    @JoinColumn(insertable = false, updatable = false)
    @ManyToOne
    private RedAppleTree tree;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Colour.java

public enum Colour {
    RED,
    GREEN,
}

Apple.treeRedApple.tree同时存在。在父Apple中,类型是Tree;在子RedApple中,类型是RedAppleTree

现在,当项目运行时,我得到:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.example.demo.dao.RedApple.tree in com.example.demo.dao.RedAppleTree.apples
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean (AbstractAutowireCapableBeanFactory.java:1628)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean (AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean (AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject (AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton (DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean (AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean (AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean (AbstractApplicationContext.java:1081)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization (AbstractApplicationContext.java:856)
    at org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:542)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh (EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh (SpringApplication.java:737)
    at org.springframework.boot.SpringApplication.refreshContext (SpringApplication.java:370)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:314)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1162)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1151)
    at com.example.demo.DemoApplication.main (DemoApplication.java:13)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:527)
    at java.lang.Thread.run (Thread.java:834)
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.example.demo.dao.RedApple.tree in com.example.demo.dao.RedAppleTree.apples
    at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass (CollectionBinder.java:769)
    at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass (CollectionBinder.java:719)
    at org.hibernate.cfg.CollectionSecondPass.doSecondPass (CollectionSecondPass.java:54)
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses (InFlightMetadataCollectorImpl.java:1655)
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses (InFlightMetadataCollectorImpl.java:1623)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete (MetadataBuildingProcess.java:278)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata (EntityManagerFactoryBuilderImpl.java:847)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build (EntityManagerFactoryBuilderImpl.java:874)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory (SpringHibernateJpaPersistenceProvider.java:60)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory (LocalContainerEntityManagerFactoryBean.java:353)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory (AbstractEntityManagerFactoryBean.java:370)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet (AbstractEntityManagerFactoryBean.java:359)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods (AbstractAutowireCapableBeanFactory.java:1687)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean (AbstractAutowireCapableBeanFactory.java:1624)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean (AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean (AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject (AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton (DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean (AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean (AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean (AbstractApplicationContext.java:1081)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization (AbstractApplicationContext.java:856)
    at org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:542)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh (EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh (SpringApplication.java:737)
    at org.springframework.boot.SpringApplication.refreshContext (SpringApplication.java:370)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:314)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1162)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1151)
    at com.example.demo.DemoApplication.main (DemoApplication.java:13)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:527)
    at java.lang.Thread.run (Thread.java:834)

现在我可以重命名其中一个属性来解决这个问题,但在我正在处理的实际项目中,它会导致更多的更改。

是否可以保持属性名称不变?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-23 14:41:36

在你的父类和子类中复制你的"tree“属性是一个问题。我相信这里的例子会做你想要的。

Tree.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "tree")
@DiscriminatorColumn(name = "colour")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Tree<APPLE extends Apple> {

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "tree", targetEntity = Apple.class)
    private Set<APPLE> apples = Sets.newHashSet();

    //... getters & setters
}

Apple.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Table(name = "apple")
@Entity
@DiscriminatorColumn(name = "colour")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Apple<TREE extends Tree> {

    @Id
    @GeneratedValue
    private Long id;

    @JoinColumn(name = "tree_id")
    @ManyToOne(targetEntity = Tree.class)
    private TREE tree;

}

RedAppleTree.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "tree")
@DiscriminatorColumn(name = "colour")
@DiscriminatorValue("RED")
public class RedAppleTree extends Tree<RedApple> {
}

RedApple.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Entity
@Table(name = "apple")
@DiscriminatorColumn(name = "colour")
@DiscriminatorValue("RED")
public class RedApple extends Apple<RedAppleTree> {
}

这将创建以下DB表

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
create table tree (
   colour varchar(31) not null,
    id bigint generated by default as identity (start with 1),
    primary key (id)
);
create table apple (
   colour varchar(31) not null,
    id bigint generated by default as identity (start with 1),
    tree_id bigint,
    primary key (id)
)

然后,当我运行以下代码时

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void test() {

    RedAppleTree tree = new RedAppleTree();
    session.persist(tree);

    GreenAppleTree greenTree = new GreenAppleTree();
    session.persist(greenTree);

    RedApple apple = new RedApple();
    apple.setTree(tree);
    session.persist(apple);

    tree.getApples().add(apple);
    session.flush();
    session.clear();
    
    tree = session.get(RedAppleTree.class, tree.getId());

    System.err.println(session.createCriteria(RedAppleTree.class).list());
}

这将产生以下SQL (在启用hibernate-sql-logging的情况下运行)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Hibernate: 
insert 
into
    tree
    (id, version, colour) 
values
    (default, ?, 'RED')
Hibernate: 
insert 
into
    tree
    (id, version, colour) 
values
    (default, ?, 'GREEN')
Hibernate: 
insert 
into
    apple
    (id, version, tree_id, colour) 
values
    (default, ?, ?, 'RED')
Hibernate: 
select
    redappletr0_.id as id2_409_0_,
    redappletr0_.version as version3_409_0_ 
from
    tree redappletr0_ 
where
    redappletr0_.id=? 
    and redappletr0_.colour='RED'
Hibernate: 
select
    this_.id as id2_409_0_,
    this_.version as version3_409_0_ 
from
    tree this_ 
where
    this_.colour='RED'

我相信这应该可以解决你的基本问题。

票数 1
EN

Stack Overflow用户

发布于 2020-10-14 07:47:36

事实是,我从来没有遇到过类似的问题,合乎逻辑的事情,一个好的做法是更改属性的名称,以区分每个属性引用的实体,编译器会告诉您在哪里更改它。

您可以尝试在关系中指定子类,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mappedBy = "tree", targetEntity = RedAppleTree.class

但我重申,最好的选择是更改属性的名称,即使这涉及到更多的工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64347162

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文