Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA: How to express a unique constraint including an @ElementCollection column?

This is my JPA entity class:

@Cacheable
@Entity
public class JpaItemSearchRequest implements ItemSearchRequest {

    @Id
    @GeneratedValue
    private long id;

    @Enumerated(EnumType.STRING)
    private SearchIndex searchIndex;

    private String browseNode;
    private String keywords;

    @Enumerated(EnumType.STRING)
    @ElementCollection
    private Set<ResponseGroup> responseGroups = new HashSet<ResponseGroup>();

    private int itemPage;

    @Enumerated(EnumType.STRING)
    private Locale locale;

    ... end of fields ...
}

SearchIndex, ResponseGroup, and Locale are enums.

This class has a rather complex unique constraint: a combination of (searchIndex, browseNode, keywords, responseGroups, itemPage, locale) is considered unique.

So I added the following constraint annotation to the class:

@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "searchIndex", "browseNode", "keywords", "responseGroups", "itemPage", "locale" }) })

When I try to exercise my class, I get the following exception:

 org.hibernate.AnnotationException: Unable to create unique key constraint (searchIndex, browseNode, keywords, responseGroups, itemPage, locale) on table JpaItemSearchRequest: database column responseGroups not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
    at org.hibernate.cfg.Configuration.buildUniqueKeyFromColumnNames(Configuration.java:1584) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final]
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1386) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final]
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final]
    at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94) ~[hibernate-entitymanager-4.1.7.Final.jar:4.1.7.Final]
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905) ~[hibernate-entitymanager-4.1.7.Final.jar:4.1.7.Final]
    ... 74 common frames omitted

(I use Hibernate 4.1.7.Final as the JPA implementation/service provider)

The exception gist is: database column responseGroups not found.

If I don't specify that constraint, behind the scenes, for my single entity class, Hibernate generates two tables: One for all the "simple" entity data, and one additional table for the Set<ResponseGroup> responseGroups entity data:

CREATE TABLE `jpaitemsearchrequest` (
    `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `browseNode` VARCHAR(255) NULL DEFAULT NULL,
    `itemPage` INT(11) NOT NULL,
    `keywords` VARCHAR(255) NULL DEFAULT NULL,
    `locale` VARCHAR(255) NULL DEFAULT NULL,
    `searchIndex` VARCHAR(255) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=3;

...

CREATE TABLE `jpaitemsearchrequest_responsegroups` (
    `JpaItemSearchRequest_id` BIGINT(20) NOT NULL,
    `responseGroups` VARCHAR(255) NULL DEFAULT NULL,
    INDEX `FKC217757B99AE0422` (`JpaItemSearchRequest_id`),
    CONSTRAINT `FKC217757B99AE0422` FOREIGN KEY (`JpaItemSearchRequest_id`) REFERENCES `jpaitemsearchrequest` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

How can I correctly express my constraint?


Edit

This question used to read:
JPA: Unique constraint across a Set (...unique constraint on another table)

Further thinking about my problem, I'm convinced it can be boiled down to the following question:
JPA: How to express a unique constraint including an @ElementCollection column?

like image 571
Abdull Avatar asked Feb 03 '13 13:02

Abdull


1 Answers

Unique constraint over columns in collection table can be defined by using @CollectionTable with element collection.

@CollectionTable(
    uniqueConstraints= @UniqueConstraint(columnNames={"col1","col2"})
)

As said, those are columns of table where element collection is mapped. There is no way to have unique constraint over columns in multiple tables.

like image 107
Mikko Maunu Avatar answered Oct 26 '22 03:10

Mikko Maunu