Hibernate / JPA映射具有相同名称的复合主键和外键

时间:2016-02-23 11:01:19

标签: java hibernate jpa

我的数据库是:

TABLE1
"FILE_ID" NUMBER NOT NULL ENABLE, 
"GEO_ZONE" VARCHAR2(2 BYTE) NOT NULL ENABLE,
PRIMARY KEY ("FILE_ID", "GEO_ZONE")

TABLE2
"FILE_ID" NUMBER NOT NULL ENABLE, 
"GEO_ZONE" VARCHAR2(2 BYTE) NOT NULL ENABLE,
"RECORD_NUM" NUMBER, 
PRIMARY KEY ("FILE_ID", "GEO_ZONE", "RECORD_NUM"),
CONSTRAINT "FK_8ULB8IEBEU6A0VK1WTNQA3MCY" FOREIGN KEY ("FILE_ID", "GEO_ZONE")

我们可以在Table2中为表1中的多行添加1行。

我的TABLE1实体是:

@Entity
@Table(name = "TABLE1")
@IdClass(Table1Id.class)
public class Table1Entity implements Serializable {
private static final long serialVersionUID = 7825109721507305471L;

@Id
@Column(name = "FILE_ID", insertable = false, updatable = false)
private Long fileId;

@Id
@Column(name = "GEO_ZONE", insertable = false, updatable = false)
private String geoZone;

... Others attributes and getter and setter

我的Table1Id类是:

public class Table1Id implements Serializable {
    private static final long serialVersionUID = -8618317422024959144L;

    private Long fileId;

    private String geoZone;

... Others attributes and getter and setter

我的TABLE2实体是:

@Entity
@Table(name = "TABLE2")
@IdClass(Table2Id.class)
public class Table2Entity implements Serializable {

    private static final long serialVersionUID = -1344497166638156145L;

    @Id
    @Column(name = "FILE_ID", insertable = false, updatable = false)
    private Long fileId;

    @Id
    @Column(name = "GEO_ZONE", insertable = false, updatable = false)
    private String geoZone;

    @Id
    @Column(name = "RECORD_NUM")
    private Long recordNum;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumns({@JoinColumn(name = "FILE_ID", insertable = false, updatable = false), //
            @JoinColumn(name = "GEO_ZONE", insertable = false, updatable = false)})
    private Table1Entity table1Entity;


... Others attributes and getter and setter

我的Table2Id类是:

public class Table2Id implements Serializable {

    private static final long serialVersionUID = -4599660767213338871L;

    private Long fileId;

    private String geoZone;

    private Long recordNum;

... Others attributes and getter and setter

当我尝试启动我的tomcat时,出现以下错误:

org.hibernate.MappingException: Foreign key (FK_8ulb8iebeu6a0vk1wtnqa3mcy:TABLE2 [FILE_ID,GEO_ZONE])) must have same number of columns as the referenced primary key (TABLE1 [FILE_ID])

我尝试使用引用列,主键连接列以及许多其他内容但通过在Internet上读取它,它可以解决数据库模型化问题。 我认为问题是主键和外键在2个表中具有相同的名称,但我可能是错的...... 我请你确认一下,或者你是否有解决方案。

谢谢你的提前,因为1周我搜索找到解决方案,但找不到任何解决方案。

编辑: 我将表名更改为toto,这在我的基础中不存在,并且我与另一个fk id有相同的错误。似乎hibernate没有连接到我的数据库。 但是,如果我从TABLE1中删除复合键,只在Table2Entity中的join_column中使用file_id,并且项目可以工作,但这不是我想要的。 这让我生病了,我不明白问题出在哪里。 并且错误告诉RDJ_STAT pk只是FILE_ID而不是,就像hibernate被喝醉一样

EDIT2: ojdbc版本可能有问题吗? 没有解决方案?

EDIT3:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa">

    <context:property-placeholder location="classpath:application.properties" />

    <context:annotation-config/>

     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="${db.driver}" />
            <property name="url" value="${db.url}" />
            <property name="username" value="${db.username}" />
            <property name="password" value="${db.password}" />
    </bean>

    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="true"/>
        <property name="generateDdl" value="true"/>
        <property name="database" value="MYSQL"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <property name="persistenceXmlLocation" value="classpath:persistence.xml"></property>
        <!-- spring based scanning for entity classes>-->
    </bean>

     <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

    <jpa:repositories base-package="com.sacre.repository" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/>

</beans>

2 个答案:

答案 0 :(得分:1)

错误问题是@ManyToOne尝试使用@OneToOne

    @OneToMany(fetch = FetchType.EAGER)
    ...
    private Table1Entity table1Entity;

答案 1 :(得分:0)

是的,可能是这两个类都使用相同的名称。尝试在加入列定义中添加table="TABLE1"

编辑:将table="TABLE1"放入eclipse中导致验证错误。我想文件说如果省略它,它将指向目标实体表。但是,上面描述的类会导致此验证错误。

  

当有多个连接列时,必须指定引用的列名

我通过添加referencedColumnName来解决这个问题:

@JoinColumns({@JoinColumn(name = "FILE_ID", referencedColumnName="FILE_ID", insertable = false, updatable = false), //
        @JoinColumn(name = "GEO_ZONE", referencedColumnName="GEO_ZONE", insertable = false, updatable = false)})

因此,它在Wildfly 9.0.2.Final下运行,并创建以下SQL:

create table TABLE1 (FILE_ID bigint not null, GEO_ZONE varchar(255) not null, primary key (FILE_ID, GEO_ZONE))

create table TABLE2 (FILE_ID bigint not null, GEO_ZONE varchar(255) not null, RECORD_NUM bigint not null, primary key (FILE_ID, GEO_ZONE, RECORD_NUM))

alter table TABLE2 add constraint FK_4f6hkpolrjfbm222dd74seh6 foreign key (FILE_ID, GEO_ZONE) references TABLE1

所以,我没有尝试插入任何行或任何东西,但似乎你可以有多个TABLE2条目引用TABLE1条目,每个条目都有一个带有此模式的唯一recordNum