【问题标题】:JPA Mapping OneToMany between composite key with diferent column namesJPA在具有不同列名的复合键之间一对多映射
【发布时间】:2017-11-19 05:03:28
【问题描述】:

我试图从 LEGACY 数据库模式创建一个 jpa 模型。

我在 mysql 中创建了一个简单的数据库,并在 eclipse(反向)中使用 jpa 工具生成了模型。

jpa工具生成的代码在我的springboot项目中报错:

org.springframework.beans.factory.BeanCreationException:创建名为“entityManagerFactory”的bean时出错 在类路径资源[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]中定义:

init 方法调用失败;嵌套异常是 org.hibernate.AnnotationException: referencedColumnNames(id) of stackoverflow.entity.SecondTable.mainTable 引用 stackoverflow.entity.MainTable 未映射到单个属性

我认为这是有道理的,因为在 SecondTable 中我的 PK 是 (id, day) 而在 MainTable 中是 (id, year, month, code)。 现在的想法是让 id 相关。

几个链接: https://gigsterous.github.io/engineering/2016/09/25/spring-boot-2.html

对于属性覆盖(可能指定不相关的列) http://techqa.info/programming/question/33620473/hibernate-bidirectional-one-to-many-with-composite-key

JPA: Entity mapping with composite primary key and single key

这些是 jpa 工具创建的 4 个实体:

@Entity
@Table(name="main_table")
public class MainTable implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private MainTablePK id;

    private String comment;

    //bi-directional many-to-one association to SecondTable
    @OneToMany(mappedBy="mainTable")
    private List<SecondTable> secondTables;

    public MainTable() {
    }

}

@Embeddable
public class MainTablePK implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    private int id;

    private String year;

    private String month;

    private String code;

    public MainTablePK() {
    }
}

@Entity
@Table(name="second_table")
public class SecondTable implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private SecondTablePK id;


    //bi-directional many-to-one association to MainTable

    //I think I don’t need a bi-directional relationship, just from MainTable to SecondTable

    //ERROR: NOT MAPPED TO A SINGLE PROPERTY
    //I understand id in MainTable is a composite Key
    @ManyToOne
    @JoinColumn(name="id", referencedColumnName="id")
    private MainTable mainTable;


    public SecondTable() {
    }
}


@Embeddable
public class SecondTablePK implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    private int id;

    private int day;

    private int value1;

    private int value2;

    private int value3;

    public SecondTablePK() {
    }
}

SCRIPT SQL 和数据示例

DROP TABLE IF EXISTS `main_table`;
CREATE TABLE `main_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `year` char(4) NOT NULL,
  `month` char(2) NOT NULL,
  `code` char(6) NOT NULL,
  `comment` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`,`year`,`month`,`code`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

INSERT INTO `main_table` VALUES (1,'2017','01','333090','coment one');

This has a composite key

DROP TABLE IF EXISTS `second_table`;
CREATE TABLE `second_table` (
  `id` int(11) NOT NULL,
  `day` int(11) NOT NULL,
  `value1` int(11) DEFAULT NULL,
  `value2` int(11) DEFAULT NULL,
  `value3` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`,`day`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


INSERT INTO `second_table` VALUES (1,0,1,NULL,NULL),(1,1,2,NULL,NULL),(1,2,NULL,NULL,NULL),(1,3,NULL,NULL,NULL),(1,4,NULL,NULL,NULL),(1,32,NULL,NULL,NULL);

是否可以使用 JPA 来实现? 有什么建议吗?

谢谢

更新

删除了非 PK 字段 value1、value2 和 value3,是一个错字。

遵循 JPA 2.1 规范,第 2.4.1 节,示例 2,第 34,35 页与我的非常相似。

所以申请:

@MapsId("empPK")
              @JoinColumns({
@JoinColumn(name="FK1", referencedColumnName="firstName"),
@JoinColumn(name="FK2", referencedColumnName="lastName") })

我们有:

@ManyToOne
@MapsId("id") // maps the 'id' attribute of the embedded ID
@JoinColumn(name="id", referencedColumnName="id")
private MainTable mainTable;

没有进行更多更改。

我得到下一个错误: org.springframework.beans.factory.BeanCreationException:在类路径资源[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]中定义名称为“entityManagerFactory”的bean创建错误:调用init方法失败;嵌套异常是 org.hibernate.AnnotationException: 无法在@MapsId 映射中找到列引用:代码

如果我删除代码,同样的错误,但 month,如果我删除月份,同样的错误 year

谢谢

【问题讨论】:

    标签: mysql hibernate jpa


    【解决方案1】:

    首先,您的SecondTablePK 似乎不正确,因为它包含非PK 字段value1value2value3。它应该看起来像这样:

    @Embeddable
    public class SecondTablePK implements Serializable {
        //default serial version id, required for serializable classes.
        private static final long serialVersionUID = 1L;
    
        private int id;
    
        private int day;
    
        public SecondTablePK() {
        }
    }
    

    关于共享id:通常,依赖实体将引用父实体的整个主键,但您可以像这样映射关系:

    @Entity
    @Table(name="second_table")
    public class SecondTable implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @EmbeddedId
        private SecondTablePK id;
    
        private int value1;
    
        private int value2;
    
        private int value3;
    
        @ManyToOne
        @MapsId("id") // maps the 'id' attribute of the embedded ID
        @JoinColumn(name="id", referencedColumnName="id")
        private MainTable mainTable;
    
    
        public SecondTable() {
        }
    }
    

    这很像 JPA 2.1 规范第 2.4.1 节中讨论的“派生身份”。

    【讨论】:

    • 更新了我的问题,因为您的建议有误。谢谢
    • 这有点像 Hibernate 期望 SecondTablePK 包含整个主键(即 private MainTablePK mainTable 而不是“部分键”private int id)。你的外键只包含MainTable的主键的部分,这有点问题......
    • 好吧,根据另一篇类似的帖子,这似乎是不可能的,例如:stackoverflow.com/questions/42245223/…,无论如何谢谢
    猜你喜欢
    • 1970-01-01
    • 2018-05-08
    • 2021-12-01
    • 2016-06-05
    • 2016-09-18
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多