jpa 复合主键,可与唯一键连接

标签 jpa composite-primary-key unique-key jointable

这是sql表:
选项主键是名称+值

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`)
)

产品主键是增量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

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

最佳答案

根据您的架构,您的实体注释略有偏差。在您指定 'product' 和 'option' 的地方,您应该使用 '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;

顺便说一句,从长远来看,如果您切换选项表上的主键和唯一键,您的生活会变得更加轻松。

关于jpa 复合主键,可与唯一键连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13235999/

相关文章:

MYSQL 复合键 "FriendList"

primary-key - 黑白主键和唯一键有什么区别

java - Hibernate:删除父级/所有者,同时保持子级一对一的关系

java - Hibernate/JPA 在 Eclipse 中运行良好,部署时抛出 SchemaManagementException

SQL 多个外键作为主键

sqlite - 如何在 SQLite 中删除具有 2 列作为复合主键的多行?

java - 在更改和重新加载时 Play Framework 并出现 eclipselink 错误

java - 为继承字段添加 Java 注解

mysql - 如何在MySQL中插入新行,其中主键列是唯一且随机数

hadoop - 在配置单元表中为唯一 ID 添加一个新列