jpa 复合主键并可与唯一键连接
Posted
技术标签:
【中文标题】jpa 复合主键并可与唯一键连接【英文标题】:jpa composite primary key and jointable with unique key 【发布时间】:2012-10-25 12:26:43 【问题描述】:这里是 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
但我不知道如何解决这个问题
【问题讨论】:
【参考方案1】:根据您的架构,您的实体注释略有偏差。在您指定“产品”和“选项”的地方,您应该使用“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;
顺便说一句,从长远来看,如果您在 option 表上切换主键和唯一键,您的生活将会轻松得多。
【讨论】:
我的错误。我已经纠正了错字。 (我仍然有问题)。出于商业目的,最好有一个有意义的主键,并且仅将技术 id 用于数据库目的 对,但在数据库级别,您应该处理“技术”ID。您的唯一密钥将成为您的“业务密钥”。今天晚些时候我会在工作中运行你的示例。看起来它应该按原样运行。以上是关于jpa 复合主键并可与唯一键连接的主要内容,如果未能解决你的问题,请参考以下文章