Just try to use ElementCollection with Set
TweetPosted on Monday Feb 17, 2014 at 04:25PM in Technology
Just some notes about how it works, how create schemas, and how DMLs executes, and try to find its pros and cons.
Environment
- WildFly 8.0.0.Final
- Hibernate 4.3.1
- PostgreSQL 9.2.4
- postgresql-9.3-1100.jdbc41.jar
Example project
Whole project resources are available in GitHub.
Set<Basic>
Schema
jpatest=# \d setbasic Table "public.setbasic" Column | Type | Modifiers --------+--------+----------- id | bigint | not null Indexes: "setbasic_pkey" PRIMARY KEY, btree (id) Referenced by: TABLE "setbasic_set" CONSTRAINT "fk_qov1oy3cmf1wmttooahy264eh" FOREIGN KEY (setbasic_id) REFERENCES setbasic(id) jpatest=# \d setbasic_set Table "public.setbasic_set" Column | Type | Modifiers -------------+------------------------+----------- setbasic_id | bigint | not null set | character varying(255) | Foreign-key constraints: "fk_qov1oy3cmf1wmttooahy264eh" FOREIGN KEY (setbasic_id) REFERENCES setbasic(id) jpatest=#
Entry data
log
13:59:11,377 DEBUG [org.hibernate.SQL] (default task-15) insert into SetBasic (id) values (?) 13:59:11,378 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [1] as [BIGINT] - [1] 13:59:11,379 DEBUG [org.hibernate.SQL] (default task-15) insert into SetBasic_set (SetBasic_id, set) values (?, ?) 13:59:11,379 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [1] as [BIGINT] - [1] 13:59:11,379 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [2] as [VARCHAR] - [hige] 13:59:11,380 DEBUG [org.hibernate.SQL] (default task-15) insert into SetBasic_set (SetBasic_id, set) values (?, ?) 13:59:11,380 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [1] as [BIGINT] - [1] 13:59:11,380 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [2] as [VARCHAR] - [hoge] 13:59:11,381 DEBUG [org.hibernate.SQL] (default task-15) insert into SetBasic_set (SetBasic_id, set) values (?, ?) 13:59:11,381 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [1] as [BIGINT] - [1] 13:59:11,381 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [2] as [VARCHAR] - [fuge]
table
jpatest=# select * from setbasic; id ---- 1 (1 row) jpatest=# select * from setbasic_set; setbasic_id | set -------------+------ 1 | hige 1 | hoge 1 | fuge (3 rows) jpatest=#
Find
14:01:27,838 DEBUG [org.hibernate.SQL] (default task-8) select setbasic0_.id as id1_2_0_ from SetBasic setbasic0_ where setbasic0_.id=? 14:01:27,838 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [1] as [BIGINT] - [1] 14:01:27,839 DEBUG [org.hibernate.SQL] (default task-8) select set0_.SetBasic_id as SetBasic1_2_0_, set0_.set as set2_3_0_ from SetBasic_set set0_ where set0_.SetBasic_id=? 14:01:27,840 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-8) binding parameter [1] as [BIGINT] - [1] 14:01:27,839 FINE [org.nailedtothex.jpatest.set.SetBasicTestDataManipulator] (default task-8) find(): [hige, hoge, fuge]
Add
log
14:03:45,339 DEBUG [org.hibernate.SQL] (default task-15) select setbasic0_.id as id1_2_0_ from SetBasic setbasic0_ where setbasic0_.id=? 14:03:45,340 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [1] as [BIGINT] - [1] 14:03:45,341 DEBUG [org.hibernate.SQL] (default task-15) select set0_.SetBasic_id as SetBasic1_2_0_, set0_.set as set2_3_0_ from SetBasic_set set0_ where set0_.SetBasic_id=? 14:03:45,341 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [1] as [BIGINT] - [1] 14:03:45,345 DEBUG [org.hibernate.SQL] (default task-15) insert into SetBasic_set (SetBasic_id, set) values (?, ?) 14:03:45,345 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [1] as [BIGINT] - [1] 14:03:45,345 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-15) binding parameter [2] as [VARCHAR] - [hege]
table
jpatest=# select * from setbasic_set; setbasic_id | set -------------+------ 1 | hoge 1 | hige 1 | fuge 1 | hege (4 rows) jpatest=#
Remove
log
14:05:08,367 DEBUG [org.hibernate.SQL] (default task-5) select setbasic0_.id as id1_2_0_ from SetBasic setbasic0_ where setbasic0_.id=? 14:05:08,368 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-5) binding parameter [1] as [BIGINT] - [1] 14:05:08,369 DEBUG [org.hibernate.SQL] (default task-5) select set0_.SetBasic_id as SetBasic1_2_0_, set0_.set as set2_3_0_ from SetBasic_set set0_ where set0_.SetBasic_id=? 14:05:08,369 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-5) binding parameter [1] as [BIGINT] - [1] 14:05:08,374 DEBUG [org.hibernate.SQL] (default task-5) delete from SetBasic_set where SetBasic_id=? and set=? 14:05:08,374 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-5) binding parameter [1] as [BIGINT] - [1] 14:05:08,374 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-5) binding parameter [2] as [VARCHAR] - [hige]
table
jpatest=# select * from setbasic_set; setbasic_id | set -------------+------ 1 | hoge 1 | fuge (2 rows) jpatest=#
Set<Embeddable>
Schema
jpatest=# \d setembeddableparent Table "public.setembeddableparent" Column | Type | Modifiers --------+--------+----------- id | bigint | not null Indexes: "setembeddableparent_pkey" PRIMARY KEY, btree (id) Referenced by: TABLE "setembeddableparent_setembeddablechilds" CONSTRAINT "fk_r8ikgl74hjndujhjwuvnkt59m" FOREIGN KEY (setembeddableparent_id) REFERENCES setembeddableparent(id) jpatest=# \d setembeddableparent_setembeddablechilds Table "public.setembeddableparent_setembeddablechilds" Column | Type | Modifiers ------------------------+------------------------+----------- setembeddableparent_id | bigint | not null embfield1 | character varying(255) | embfield2 | character varying(255) | Foreign-key constraints: "fk_r8ikgl74hjndujhjwuvnkt59m" FOREIGN KEY (setembeddableparent_id) REFERENCES setembeddableparent(id) jpatest=#
Entry data
log
14:06:58,199 DEBUG [org.hibernate.SQL] (default task-12) insert into SetEmbeddableParent (id) values (?) 14:06:58,199 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [1] as [BIGINT] - [1] 14:06:58,200 DEBUG [org.hibernate.SQL] (default task-12) insert into SetEmbeddableParent_setEmbeddableChilds (SetEmbeddableParent_id, embField1, embField2) values (?, ?, ?) 14:06:58,200 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [1] as [BIGINT] - [1] 14:06:58,200 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [2] as [VARCHAR] - [child3field1] 14:06:58,201 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [3] as [VARCHAR] - [child3field2] 14:06:58,201 DEBUG [org.hibernate.SQL] (default task-12) insert into SetEmbeddableParent_setEmbeddableChilds (SetEmbeddableParent_id, embField1, embField2) values (?, ?, ?) 14:06:58,202 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [1] as [BIGINT] - [1] 14:06:58,202 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [2] as [VARCHAR] - [child2field1] 14:06:58,202 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [3] as [VARCHAR] - [child2field2] 14:06:58,202 DEBUG [org.hibernate.SQL] (default task-12) insert into SetEmbeddableParent_setEmbeddableChilds (SetEmbeddableParent_id, embField1, embField2) values (?, ?, ?) 14:06:58,202 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [1] as [BIGINT] - [1] 14:06:58,203 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [2] as [VARCHAR] - [child1field1] 14:06:58,203 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-12) binding parameter [3] as [VARCHAR] - [child1field2]
table
jpatest=# select * from setembeddableparent; id ---- 1 (1 row) jpatest=# select * from setembeddableparent_setembeddablechilds; setembeddableparent_id | embfield1 | embfield2 ------------------------+--------------+-------------- 1 | child3field1 | child3field2 1 | child2field1 | child2field2 1 | child1field1 | child1field2 (3 rows) jpatest=#
Find
14:10:32,579 DEBUG [org.hibernate.SQL] (default task-6) select setembedda0_.id as id1_4_0_ from SetEmbeddableParent setembedda0_ where setembedda0_.id=? 14:10:32,579 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [BIGINT] - [1] 14:10:32,580 DEBUG [org.hibernate.SQL] (default task-6) select setembedda0_.SetEmbeddableParent_id as SetEmbed1_4_0_, setembedda0_.embField1 as embField2_5_0_, setembedda0_.embField2 as embField3_5_0_ from SetEmbeddableParent_setEmbeddableChilds setembedda0_ where setembedda0_.SetEmbeddableParent_id=? 14:10:32,581 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [BIGINT] - [1] 14:10:32,580 FINE [org.nailedtothex.jpatest.set.SetEmbeddableTestDataManipulator] (default task-6) [SetEmbeddableChild [embField1=child3field1, embField2=child3field2], SetEmbeddableChild [embField1=child2field1, embField2=child2field2], SetEmbeddableChild [embField1=child1field1, embField2=child1field2]]
Add
log
14:12:20,219 DEBUG [org.hibernate.SQL] (default task-13) select setembedda0_.id as id1_4_0_ from SetEmbeddableParent setembedda0_ where setembedda0_.id=? 14:12:20,220 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-13) binding parameter [1] as [BIGINT] - [1] 14:12:20,221 DEBUG [org.hibernate.SQL] (default task-13) select setembedda0_.SetEmbeddableParent_id as SetEmbed1_4_0_, setembedda0_.embField1 as embField2_5_0_, setembedda0_.embField2 as embField3_5_0_ from SetEmbeddableParent_setEmbeddableChilds setembedda0_ where setembedda0_.SetEmbeddableParent_id=? 14:12:20,221 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-13) binding parameter [1] as [BIGINT] - [1] 14:12:20,225 DEBUG [org.hibernate.SQL] (default task-13) insert into SetEmbeddableParent_setEmbeddableChilds (SetEmbeddableParent_id, embField1, embField2) values (?, ?, ?) 14:12:20,225 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-13) binding parameter [1] as [BIGINT] - [1] 14:12:20,225 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-13) binding parameter [2] as [VARCHAR] - [child4field1] 14:12:20,225 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-13) binding parameter [3] as [VARCHAR] - [child4field2]
table
jpatest=# select * from setembeddableparent_setembeddablechilds; setembeddableparent_id | embfield1 | embfield2 ------------------------+--------------+-------------- 1 | child1field1 | child1field2 1 | child2field1 | child2field2 1 | child3field1 | child3field2 1 | child4field1 | child4field2 (4 rows)
Remove
log
14:14:48,499 DEBUG [org.hibernate.SQL] (default task-9) select setembedda0_.id as id1_4_0_ from SetEmbeddableParent setembedda0_ where setembedda0_.id=? 14:14:48,499 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [1] as [BIGINT] - [1] 14:14:48,500 DEBUG [org.hibernate.SQL] (default task-9) select setembedda0_.SetEmbeddableParent_id as SetEmbed1_4_0_, setembedda0_.embField1 as embField2_5_0_, setembedda0_.embField2 as embField3_5_0_ from SetEmbeddableParent_setEmbeddableChilds setembedda0_ where setembedda0_.SetEmbeddableParent_id=? 14:14:48,500 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [1] as [BIGINT] - [1] 14:14:48,500 FINE [org.nailedtothex.jpatest.set.SetEmbeddableTestDataManipulator] (default task-9) [SetEmbeddableChild [embField1=child3field1, embField2=child3field2], SetEmbeddableChild [embField1=child2field1, embField2=child2field2], SetEmbeddableChild [embField1=child1field1, embField2=child1field2]] 14:14:48,505 DEBUG [org.hibernate.SQL] (default task-9) delete from SetEmbeddableParent_setEmbeddableChilds where SetEmbeddableParent_id=? and embField1=? and embField2=? 14:14:48,505 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [1] as [BIGINT] - [1] 14:14:48,505 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [2] as [VARCHAR] - [child1field1] 14:14:48,506 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-9) binding parameter [3] as [VARCHAR] - [child1field2]
table
jpatest=# select * from setembeddableparent_setembeddablechilds; setembeddableparent_id | embfield1 | embfield2 ------------------------+--------------+-------------- 1 | child2field1 | child2field2 1 | child3field1 | child3field2 (2 rows) jpatest=#
Update
log
15:07:27,811 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-7) binding parameter [1] as [BIGINT] - [1] 15:07:27,812 DEBUG [org.hibernate.SQL] (default task-7) select setembedda0_.SetEmbeddableParent_id as SetEmbed1_2_0_, setembedda0_.embField1 as embField2_3_0_, setembedda0_.embField2 as embField3_3_0_ from SetEmbeddableParent_setEmbeddableChilds setembedda0_ where setembedda0_.SetEmbeddableParent_id=? 15:07:27,812 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-7) binding parameter [1] as [BIGINT] - [1] 15:07:27,815 DEBUG [org.hibernate.SQL] (default task-7) delete from SetEmbeddableParent_setEmbeddableChilds where SetEmbeddableParent_id=? and embField1=? and embField2=? 15:07:27,815 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-7) binding parameter [1] as [BIGINT] - [1] 15:07:27,815 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-7) binding parameter [2] as [VARCHAR] - [child2field1] 15:07:27,815 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-7) binding parameter [3] as [VARCHAR] - [child2field2] 15:07:27,816 DEBUG [org.hibernate.SQL] (default task-7) insert into SetEmbeddableParent_setEmbeddableChilds (SetEmbeddableParent_id, embField1, embField2) values (?, ?, ?) 15:07:27,816 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-7) binding parameter [1] as [BIGINT] - [1] 15:07:27,816 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-7) binding parameter [2] as [VARCHAR] - [child2field1] 15:07:27,816 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-7) binding parameter [3] as [VARCHAR] - [child2field2-updated]
table
jpatest=# select * from setembeddableparent_setembeddablechilds order by embfield1; setembeddableparent_id | embfield1 | embfield2 ------------------------+--------------+---------------------- 1 | child1field1 | child1field2 1 | child2field1 | child2field2-updated 1 | child3field1 | child3field2 (3 rows) jpatest=#
Add a duplicate element
14:13:59,763 DEBUG [org.hibernate.SQL] (default task-14) select setembedda0_.id as id1_4_0_ from SetEmbeddableParent setembedda0_ where setembedda0_.id=? 14:13:59,764 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [1] as [BIGINT] - [1] 14:13:59,765 DEBUG [org.hibernate.SQL] (default task-14) select setembedda0_.SetEmbeddableParent_id as SetEmbed1_4_0_, setembedda0_.embField1 as embField2_5_0_, setembedda0_.embField2 as embField3_5_0_ from SetEmbeddableParent_setEmbeddableChilds setembedda0_ where setembedda0_.SetEmbeddableParent_id=? 14:13:59,765 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-14) binding parameter [1] as [BIGINT] - [1]
- No changes are made to DB.
Remove a element that not exist
14:16:48,827 DEBUG [org.hibernate.SQL] (default task-10) select setembedda0_.id as id1_4_0_ from SetEmbeddableParent setembedda0_ where setembedda0_.id=? 14:16:48,828 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-10) binding parameter [1] as [BIGINT] - [1] 14:16:48,829 DEBUG [org.hibernate.SQL] (default task-10) select setembedda0_.SetEmbeddableParent_id as SetEmbed1_4_0_, setembedda0_.embField1 as embField2_5_0_, setembedda0_.embField2 as embField3_5_0_ from SetEmbeddableParent_setEmbeddableChilds setembedda0_ where setembedda0_.SetEmbeddableParent_id=? 14:16:48,829 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-10) binding parameter [1] as [BIGINT] - [1]
- No changes are made to DB.
Nested collection is prohibited
- It said @ElementCollection can be used with embeddable or basic type only.
Conclusion
Pros
- It works well as expected for some operations of Set API. it prevents that add duplicated elements.
- It can reduce some annoying codes.
Cons
- All elements are need to being fetched for manipulate, so maybe it is not good for large sets.
- Child elements are not entities, so use of some convenient operations is impossible.
Remarks
- Maybe it's good for proto-typing.
- But I'm not sure about whether it is appropriate for production systems especially high-traffic concurrent systems.
- For appropriate size sets, maybe 2nd level cache would be great help for its performance.
Tags: jpa