复合键Hibernate

时间:2011-12-14 18:19:53

标签: hibernate

我想创建一个表,其中id是由字符串组成的。这就是我做的是遵循一些示例和文档:

       @Entity
@Table(name = "media_locator")
public class MediaLocator {

    private List<MediaObject> mediaObjects;
    private MediaLocatorPK primaryKey = new MediaLocatorPK();

//    @Id
//    @GeneratedValue(strategy = GenerationType.AUTO)
//    @Column(name = "id", unique = true, nullable = false)
//    public int getId() {
//        return id;
//    }
//
//    public void setId(int id) {
//         this.id = id;
//    }

    @EmbeddedId
    public MediaLocatorPK getPrimaryKey() {
        return primaryKey;
    }

    public void setPrimaryKey(MediaLocatorPK primaryKey) {
        this.primaryKey = primaryKey;
    }



//    @Column(name = "location", length = 200)
    public String getLocation() {
        return primaryKey.getLocation();
    }


    public void setLocation(String location) {
        this.primaryKey.setLocation(location);
    }

//    @Column(name = "description", length = 200, nullable = false)
    public String getDescription() {
        return primaryKey.getDescription();
    }

    public void setDescription(String description) {
        this.primaryKey.setDescription(description);
    }


//    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="mediaLocator")    
//    public List<MediaObject> getMediaObjects() {
//        return mediaObjects;
//    }
//
//    public void setMediaObjects(List<MediaObject> mediaObjects) {
//         mediaObjects = mediaObjects;
//    }


    @ManyToMany(
            cascade={CascadeType.ALL},  
            fetch=FetchType.LAZY)
    @JoinTable(name = "media_object_location", 
            joinColumns=@JoinColumn(name="mediaLocator_id"),
            inverseJoinColumns=@JoinColumn(name="mediaObject_id"))  
    public List<MediaObject> getMediaObjects() {
        return mediaObjects;
    }

    public void setMediaObjects(List<MediaObject> mediaObjects) {
        this.mediaObjects = mediaObjects;
    }


//    @Column(name = "protocol", length = 200, nullable = false)
    public String getProtocol() {
        return primaryKey.getProtocol();
    }

    public void setProtocol(String protocol) {
        this.primaryKey.setProtocol(protocol);
    }
//    @Column(name = "host", length = 200, nullable = false)
    public String getHost() {
        return primaryKey.getHost();
    }

    public void setHost(String host) {
        this.primaryKey.setHost(host);
    }
//    @Column(name = "port", length = 200, nullable = false)
    public String getPort() {
        return primaryKey.getPort();
    }

    public void setPort(String port) {
        this.primaryKey.setPort(port);
    }
//    @Column(name = "path", length = 200, nullable = false)
    public String getPath() {
        return primaryKey.getPath();
    }

    public void setPath(String path) {
        this.primaryKey.setPath(path);
    }

@Embeddable class MediaLocatorPK implements Serializable
{
  private String location;
  private String description;
  private String protocol;
  private String host;
  private String port;
  private String path;

    public String getLocation() {
        return location;
    }
    public void setLocation(String location) {
        this.location = location;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getProtocol() {
        return protocol;
    }
    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }
    public String getHost() {
        return host;
    }
    public void setHost(String host) {
        this.host = host;
    }
    public String getPort() {
        return port;
    }
    public void setPort(String port) {
        this.port = port;
    }
    public String getPath() {
        return path;
    }
    public void setPath(String path) {
        this.path = path;
    }


}

之前,我自动生成了一个id,并且每个属性在表格中都有一个列,例如@Column(name = "location", length = 200)

通过这种方式,由于与其他对象的关系引用,我无法存储数据

Caused by: org.hibernate.AnnotationException: A Foreign key refering com.app.MediaLocator from com.app.MediaObject has the wrong number of column. should be 6
    at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:429)
    at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1443)
    at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1262)
    at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:693)
    at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:628)
    at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:65)
    at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1686)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1393)
    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:1469)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1409)

这个特定的关系是:

@ManyToMany(
            cascade={CascadeType.ALL},  
            fetch=FetchType.LAZY)
    @JoinTable(name = "media_object_location", 
            joinColumns=@JoinColumn(name="mediaLocator_id"),
            inverseJoinColumns=@JoinColumn(name="mediaObject_id"))  
    public List<MediaObject> getMediaObjects() {
        return mediaObjects;
    }

    public void setMediaObjects(List<MediaObject> mediaObjects) {
        this.mediaObjects = mediaObjects;
    }

从mediaObject方面:

@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY, mappedBy = "mediaObjects")
    public List<MediaLocator> getMediaLocators() {
        return mediaLocators;
    }

    public void setMediaLocators(List<MediaLocator> mediaLocators) {
        this.mediaLocators = mediaLocators;
    }

我做错了什么?

提前致谢

1 个答案:

答案 0 :(得分:2)

将属性移动到可嵌入类后,需要将它们从主类中删除,只有一个嵌入类的引用,因此在您的示例中,您需要从{{1}中删除所有属性,如位置}。class。

财产MediaLocator在你的id中做了什么?由于您的类中没有特定的列注释,因此hibernate会尝试将每个属性映射到表列,如果属性和表列的命名相同,它将在该映射中成功。

如果您不需要MediaLocator,请将其删除或将其标记为id

这段代码将重现您所获得的相同错误。

学生班

@Transient

学生PK课程:

package com.mumz.test.jpa.embedded.manytomany;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="STUDENT")
public class StudentMTM {

    private StudentMTMPK    studentPK   = null;
    private Set<Address>      address     = null;

    public StudentMTM(StudentMTMPK studentPK, Set<Address> address) {
        super();
        this.studentPK = studentPK;
        this.address = address;
    }

    /**
     * @return the id
     */
    public Integer getId() {
        return studentPK.getId();
    }

    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        studentPK.setId(id);
    }

    /**
     * @return the name
     */
    public String getName() {
        return studentPK.getName();
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        studentPK.setName(name);
    }
    /**
     * @param studentPK
     *            the studentPK to set
     */
    public void setStudentPK(StudentMTMPK studentPK) {
        this.studentPK = studentPK;
    }

    /**
     * @param address
     *            the address to set
     */
    public void setAddress(Set<Address> address) {
        this.address = address;
    }

    /**
     * @return the address
     */
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "STUDENT_ADDRESS", joinColumns =
        {
            @JoinColumn(name = "STUDENT_ID")
        }, inverseJoinColumns =
        {
            @JoinColumn(name = "ADDRESS_ID")
        })
    public Set<Address> getAddress() {
        return address;
    }

    /**
     * @return the studentPK
     */
    @Id
    public StudentMTMPK getStudentPK() {
        return studentPK;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((studentPK == null) ? 0 : studentPK.hashCode());
        result = prime * result + ((address == null) ? 0 : address.hashCode());
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof StudentMTM)) {
            return false;
        }
        StudentMTM other = (StudentMTM) obj;
        if (studentPK == null) {
            if (other.studentPK != null) {
                return false;
            }
        } else if (!studentPK.equals(other.studentPK)) {
            return false;
        }
        if (address == null) {
            if (other.address != null) {
                return false;
            }
        } else if (!address.equals(other.address)) {
            return false;
        }
        return true;
    }
}

地址类

package com.mumz.test.jpa.embedded.manytomany;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class StudentMTMPK implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 3686950547855931594L;
    private Integer id = null;
    private String name = null;

    public StudentMTMPK(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    /**
     * @return the id
     */
    @Column(name="STUDENT_ID")
    public Integer getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    @Column(name="STUDENT_NAME")
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof StudentMTMPK)) {
            return false;
        }
        StudentMTMPK other = (StudentMTMPK) obj;
        if (id == null) {
            if (other.id != null) {
                return false;
            }
        } else if (!id.equals(other.id)) {
            return false;
        }
        if (name == null) {
            if (other.name != null) {
                return false;
            }
        } else if (!name.equals(other.name)) {
            return false;
        }
        return true;
    }
}

如果您运行这段代码并尝试保存地址实例,您将获得

package com.mumz.test.jpa.embedded.manytomany;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="ADDRESS")
public class Address {
    private Integer id = null;
    private String addressDetails = null;

    /**
     * @return the id
     */
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="ADDRESS_ID")
    public Integer getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * @return the addressDetails
     */
    @Column(name="ADDRESS_DETAILS")
    public String getAddressDetails() {
        return addressDetails;
    }

    /**
     * @param addressDetails the addressDetails to set
     */
    public void setAddressDetails(String addressDetails) {
        this.addressDetails = addressDetails;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((addressDetails == null) ? 0 : addressDetails.hashCode());
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Address)) {
            return false;
        }
        Address other = (Address) obj;
        if (addressDetails == null) {
            if (other.addressDetails != null) {
                return false;
            }
        } else if (!addressDetails.equals(other.addressDetails)) {
            return false;
        }
        if (id == null) {
            if (other.id != null) {
                return false;
            }
        } else if (!id.equals(other.id)) {
            return false;
        }
        return true;
    }
}

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: myJPAService] Unable to configure EntityManagerFactory at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:378) at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:56) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47) at com.mumz.test.jpa.embedded.manytomany.EmbeddableTestMainApp.main(EmbeddableTestMainApp.java:9) Caused by: org.hibernate.AnnotationException: A Foreign key refering com.mumz.test.jpa.embedded.manytomany.StudentMTM from com.mumz.test.jpa.embedded.manytomany.Address has the wrong number of column. should be 2 at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:429) at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1460) at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1279) at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:710) at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:645) at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:65) at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1716) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1423) at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1375) at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1519) at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1100) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:282) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:366) 中的多少人被打破了。

现在这件作品应该可行:

学生班

StudentMTM

学生PK

package com.mumz.test.jpa.embedded.manytomany;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="STUDENT")
public class StudentMTM {

    private StudentMTMPK    studentPK   = null;
    private Integer id = null;
    private Set<Address>      address     = null;

    public StudentMTM(StudentMTMPK studentPK, Set<Address> address) {
        super();
        this.studentPK = studentPK;
        this.address = address;
    }

    /**
     * @return the id
     */
    @Column(name="STUDENT_ID")
    public Integer getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    public String getName() {
        return studentPK.getName();
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        studentPK.setName(name);
    }
    /**
     * @param studentPK
     *            the studentPK to set
     */
    public void setStudentPK(StudentMTMPK studentPK) {
        this.studentPK = studentPK;
    }

    /**
     * @param address
     *            the address to set
     */
    public void setAddress(Set<Address> address) {
        this.address = address;
    }

    /**
     * @return the address
     */
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "STUDENT_ADDRESS", joinColumns =
        {
            @JoinColumn(name = "STUDENT_ID")
        }, inverseJoinColumns =
        {
            @JoinColumn(name = "ADDRESS_ID")
        })
    public Set<Address> getAddress() {
        return address;
    }

    /**
     * @return the studentPK
     */
    @Id
    public StudentMTMPK getStudentPK() {
        return studentPK;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((studentPK == null) ? 0 : studentPK.hashCode());
        result = prime * result + ((address == null) ? 0 : address.hashCode());
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof StudentMTM)) {
            return false;
        }
        StudentMTM other = (StudentMTM) obj;
        if (studentPK == null) {
            if (other.studentPK != null) {
                return false;
            }
        } else if (!studentPK.equals(other.studentPK)) {
            return false;
        }
        if (address == null) {
            if (other.address != null) {
                return false;
            }
        } else if (!address.equals(other.address)) {
            return false;
        }
        return true;
    }
}

地址类 - 与第一个版本相比没有变化。

在第二个版本中,JoinColumn是Student的一部分,映射知道它映射到的位置。