AnnotationException:外键引用的列数错误。应该是 2

Posted

技术标签:

【中文标题】AnnotationException:外键引用的列数错误。应该是 2【英文标题】:AnnotationException: A Foreign key refering has the wrong number of column. should be 2 【发布时间】:2015-01-28 16:53:24 【问题描述】:

我正在将我的类与我的数据库表进行映射,但是在运行测试时,我收到以下错误:

Caused by: org.hibernate.AnnotationException: A Foreign key refering com.modulos.pvs.acceso.datos.entity.Provincia from com.modulos.pvs.acceso.datos.entity.Ciudad has the wrong number of column. should be 2
    at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:429)
    at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:115)
    at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1550)
    at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1473)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1389)
    at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345)
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:717)
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1541)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1479)
    ... 40 more

这些是我的课程:

//    PROVINCIA TABLE
    @Entity
    @Table(name="provincia")
    @NamedQuery(name = "Provincia.findAll", query = "SELECT p FROM Provincia p")
    public class Provincia implements Serializable 

        private static final long serialVersionUID = 1L;

        @EmbeddedId
        private ProvinciaPK id;

        private String nombreProvincia;

        // bi-directional many-to-one association to Region
        @ManyToOne(fetch=FetchType.LAZY)
        @JoinColumn(name = "codRegion")
        private Region region;

        //bi-directional many-to-one association to Ciudad
        @OneToMany(mappedBy="provincia", fetch=FetchType.LAZY)
        private List<Ciudad> ciudad;

    //GETTER AND SETTER

//TABLE CIUDAD
/**
 * The persistent class for the city database table.
 * 
 */
@Entity
@Table(name="ciudad")
@NamedQuery(name = "Ciudad.findAll", query = "SELECT c FROM Ciudad c")
public class Ciudad implements Serializable 
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private CiudadPK id;

    private String nombreCiudad;

    // bi-directional many-to-one association to Provincia
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "codProvincia", insertable = false, updatable = false)
    private Provincia provincia;

    //bi-directional many-to-one association to Direcciones
    @OneToMany(mappedBy="ciudad", fetch=FetchType.LAZY)
    private List<Direcciones> direcciones;

//  GETTER AND SETTER

两者都有主键嵌入到类中。

//PROVINCIA PK
/**
 * The primary key class for the provincia database table.
 * 
 */
@Embeddable
public class ProvinciaPK implements Serializable 
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    private String codProvincia;

    private String codRegion;

    public ProvinciaPK() 
    
    /getter and setter

//ciudad pk
/**
 * The primary key class for the region database table.
 * 
 */
@Embeddable
public class CiudadPK implements Serializable 
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    private String codCiudad;

    private String codProvincia;

    public CiudadPK() 
    
//GETTER AND SETTER

这是我的关系模型数据库

有人知道吗?那个不起作用?

编辑 30/11/2014 - 返回列表空关联 这是我的 JUnit 测试

Region region = new Region();
            region.setId(new RegionPK("RM","CHL"));

            region.setProvincias(regionDAO.getProvinciaRegion(region));

            System.out.println(region.getProvincias());

这是返回provincias关联的方法

@Transactional(readOnly=true)
@Override
public List<Provincia> getProvinciaRegion(Region region) 
    region = getRegionById(region);
    Hibernate.initialize(region.getProvincias());
    return region.getProvincias();

这个我在数据库里

【问题讨论】:

【参考方案1】:

你的班级CiudadPK 有两列。您只使用@JoinColumn,它仅限于一列。您需要使用 @JoinColumns 并列出 FK 中的两列,例如

// bi-directional many-to-one association to Provincia
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns(
  @JoinColumn(name = "codProvincia", insertable = false, updatable = false),
  @JoinColumn(name = "codRegion", insertable = false, updatable = false)
)
private Provincia provincia;

您可能还会遇到Ciudad 的其他问题,请按照此处的模式更正该问题。

【讨论】:

谢谢,它有效!但我有疑问,因为如果我的表只有一个外键,我需要两个外键?这是我没有理解的东西 您获得了复合主键,因为您在代码中使用了@EmbeddedId。这不是你的本意吗? 如果是的话,让我很困惑,但你开导了我,我明白了。否则,因为现在我尝试在课堂上返回列表 REGION asociasones,但我返回一个空列表,你知道这是为什么吗?我用有关此的信息编辑了帖子 我不知道Hibernate.initialize 是什么,那是你的自定义代码吗?最好的办法是开始一个新问题,解释你想要做什么。还要与您的域模型进行比较-您缺少 codCiudad 它可以工作,但是当我保存一个新实体 Ciudad 时,我得到一个“重复键值违反 Provincia 的唯一约束”,为什么?【参考方案2】:

从 Java 8(引入 @Repeatable)开始,不再需要包装注解 @JoinColumns

所以,你可以这样做:

// bi-directional many-to-one association to Provincia
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "codProvincia", insertable = false, updatable = false)
@JoinColumn(name = "codRegion", insertable = false, updatable = false)
private Provincia provincia;

参考资料:

Java 8's new Type Annotations

Repeating Annotations

【讨论】:

以上是关于AnnotationException:外键引用的列数错误。应该是 2的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.ExceptionInInitializerError 和 org.hibernate.AnnotationException: mappedBy 引用了一个未知的目标实体属性:

双向休眠 - org.hibernate.AnnotationException: Unknown mappedBy in: error

org.hibernate.AnnotationException

org.hibernate.AnnotationException:找不到预期的辅助表

org.hibernate.AnnotationException:没有为实体指定标识符 - 即使它是

org.hibernate.AnnotationException:没有为使用 JPA XML 实体映射的实体指定标识符