簡體   English   中英

外鍵必須與引用的主鍵具有相同的數字列

[英]Foreign key must have the same number columns as the referenced primary key

我有以下實體。

實體A

package misc;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class EntityA implements Serializable {

    private static final long serialVersionUID = -6740580086652468946L;

    @Id
    private int counter; 

}

實體B

package misc;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class EntityB implements Serializable {

    private static final long serialVersionUID = -1919957640470940855L;

    @Id
    private String name;
}

實體C

package misc;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class EntityC implements Serializable {

    private static final long serialVersionUID = -4676412878199289178L;

    @Id
    private String name;
}

歷史實體

package misc;

import java.io.Serializable;
import java.util.List;

import javax.persistence.CollectionTable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OrderColumn;
import javax.persistence.UniqueConstraint;

@Entity
public class HistoricalEntity implements Serializable {

    private static final long serialVersionUID = 4889420648637014496L;

    @Id
    @ManyToOne
    @JoinColumn
    private EntityA entityA;

    @Id
    @ManyToOne
    @JoinColumn
    private EntityB entityB;

    @ManyToMany
    @CollectionTable(uniqueConstraints = { @UniqueConstraint(columnNames = {
            "HISTORICAL_ENTITY_ENTITY_A", "HISTORICAL_ENTITY_ENTITY_B",
            "HISTORY_ID", }) })
    @OrderColumn(name = "POSITION")
    private List<EntityC> history;
}

...以及帶有空測試的配置...

package misc;

import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class TestConfiguration {

    @Bean
    public DataSource dataSource() {
        final BasicDataSource dataSource = new BasicDataSource();
        dataSource.setUrl("jdbc:postgresql://localhost:5432/mydb");
        dataSource.setDriverClassName("org.postgresql.Driver");
        dataSource.setUsername("postgres");
        dataSource.setPassword("postgres");

        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(dataSource());
        emf.setPackagesToScan("pl.xtra_klasa.utils.total.test");
        final Map<String, Object> propertyMap = emf.getJpaPropertyMap();
        propertyMap.put(org.hibernate.cfg.Environment.SHOW_SQL, true);
        propertyMap.put(org.hibernate.cfg.Environment.FORMAT_SQL, true);
        propertyMap.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, "create");
        propertyMap.put(org.hibernate.cfg.Environment.DIALECT,
                "org.hibernate.dialect.PostgreSQLDialect");
        propertyMap.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");

        final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        emf.setJpaVendorAdapter(vendorAdapter);

        return emf;
    }

    @Bean
    public EntityManager entityManager(EntityManagerFactory entityManagerFactory) {
        return entityManagerFactory.createEntityManager();
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        final JpaTransactionManager tm = new JpaTransactionManager(
                entityManagerFactory().getObject());
        return tm;
    }
}

Junit測試

package misc;

import javax.transaction.Transactional;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
@Transactional
public class MyTest {

    @Test
    public void test() {

    }
}

測試以以下異常結束,我不知道為什么會這樣。

外鍵(FK_85k7tuu55uee70x387oekb6gj:historical_entity_history [historical_entity]))必須與引用的主鍵具有相同的列數(historical_entity [entityb,entitya])

我必須補充一點,一切工作正常,但是我決定切換到org.hibernate.cfg.ImprovedNamingStrategy並刪除使用@Table(name = "TABLE_NAME")給表賦予的所有顯式名稱。

我已經為此奮斗了兩個多小時。 我怎樣才能找到問題所在?

編輯

僅使用@ElementCollection注釋屬性history會導致相同的錯誤。

...
@ElementCollection
private List<EntityC> history;
...

我自己找到了解決方案。 需要明確指定連接列。

@ManyToMany
    @CollectionTable(joinColumns = { @JoinColumn(name = "entityA"),
            @JoinColumn(name = "entityB") }, uniqueConstraints = { @UniqueConstraint(columnNames = {
            "entityA", "entityB", "history" }) })
    @OrderColumn(name = "POSITION")
    private List<EntityC> history;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM