JPA复合主键和jointable具有独特的键

问题描述:

这里的SQL表:
选择主键是名称+值
JPA复合主键和jointable具有独特的键

CREATE TABLE `option` (
    id int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(45) NOT NULL, 
    `value` varchar(45) NOT NULL, 
    PRIMARY KEY (`name`, `value`), 
    UNIQUE KEY `id_UNIQUE` (`id`) 
) 

产品主键是增量编号

CREATE TABLE `product` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(50) NOT NULL, 
    PRIMARY KEY (`id`) 
) 

一产品有几个选项(参考唯一密钥“id”)

CREATE TABLE product_option (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `id_product` int(11) NOT NULL, 
    `id_option` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `id_product` (`id_product`), 
    KEY `id_option` (`id_option`), 
    CONSTRAINT `FK_product_option` FOREIGN KEY (`id_product`) REFERENCES `product` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, 
    CONSTRAINT `FK_option_product` FOREIGN KEY (`id_option`) REFERENCES `option` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
) 

在Java方面,我已经映射 “选项” 这样

@Embeddable 
public class OptionId implements Serializable{ 
    @Column(name="value") 
    private String value; 

    @Column(name="name") 
    private String name; 
} 


@Entity @Table(name="option") 
public class Option { 

    @Column(name="id", unique=true) 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Long id; 

    @EmbeddedId 
    private OptionId primaryKey; 

    public OptionId getPrimaryKey() { 
     return primaryKey; 
    } 

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

和产品这样

@Entity 
@Table(name="product") 
public class Product { 

    @Id @Column(name="id") 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Long id; 

    @Column(name="name") 
    private String name 

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY) 
    @JoinTable(
      name="product_option", 
      joinColumns = @JoinColumn(name="id_product"), 
      inverseJoinColumns = @JoinColumn(name="id_option", referencedColumnName="id") 
    ) 
    private Set<Option> options; 
} 

然后在执行时,我得到这个错误

Caused by: java.lang.ArrayIndexOutOfBoundsException: 1 
    at org.hibernate.sql.SelectFragment.addColumns(SelectFragment.java:107) 
    at org.hibernate.persister.collection.BasicCollectionPersister.manyToManySelectFragment(BasicCollectionPersister.java:308) 
    at org.hibernate.persister.collection.BasicCollectionPersister.selectFragment(BasicCollectionPersister.java:294) 
    at org.hibernate.loader.JoinWalker.selectString(JoinWalker.java:1070) 
    at org.hibernate.loader.AbstractEntityJoinWalker.initStatementString(AbstractEntityJoinWalker.java:124) 
    at org.hibernate.loader.AbstractEntityJoinWalker.initStatementString(AbstractEntityJoinWalker.java:109) 
    at org.hibernate.loader.AbstractEntityJoinWalker.initAll(AbstractEntityJoinWalker.java:91) 
    at org.hibernate.loader.AbstractEntityJoinWalker.initAll(AbstractEntityJoinWalker.java:78) 
    at org.hibernate.loader.entity.CascadeEntityJoinWalker.<init>(CascadeEntityJoinWalker.java:52) 
    at org.hibernate.loader.entity.CascadeEntityLoader.<init>(CascadeEntityLoader.java:47) 
    at org.hibernate.persister.entity.AbstractEntityPersister.createLoaders(AbstractEntityPersister.java:3254) 
    at org.hibernate.persister.entity.AbstractEntityPersister.postInstantiate(AbstractEntityPersister.java:3191) 
    at org.hibernate.persister.entity.SingleTableEntityPersister.postInstantiate(SingleTableEntityPersister.java:728) 
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:348) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1872) 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:906) 
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74) 
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417) 
    ... 60 more 

如果我删除“referencedColumnName”,当然我得到错误

A Foreign key refering Option from Product has the wrong number of column. should be 2 

但我不知道如何解决这个问题

根据你的模式,你的实体注释稍微偏离。当你指定“产品”和“选项”,你应该使用“id_product”和“id_option”:

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY) 
@JoinTable(
     name="product_option", 
     joinColumns = @JoinColumn(name="id_product"), 
     inverseJoinColumns = @JoinColumn(name="id_option", referencedColumnName="id") 
) 
private Set<Option> options; 

顺便说一句,你的生活会容易得多,从长远来看,如果切换主并在您的选件表上提供独特的按键。

+0

我的错误。我纠正了错字。 (我仍然有问题)。出于商业目的,最好有一个有意义的主键,并使用技术ID仅用于数据库目的 – user1800633

+0

正确,但在数据库级别,您应该处理'技术'ID。你独特的钥匙成为你的'商业钥匙'。我会在今天晚些时候开始工作。它看起来应该按原样运行。 – Perception