Collections cannot be nested, and, when used in collections, embeddable types are not allowed to define other collections.
Value type collection lifecycle
package org.example.demo.hibernate;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Persistence;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager entityManager = factory.createEntityManager();
Person person = new Person();
person.getPhones().add("123-456-7890");
person.getPhones().add("456-000-1234");
entityManager.getTransaction().begin();
entityManager.persist(person);
entityManager.flush();
person.phones.clear();
entityManager.getTransaction().commit();
entityManager.clear();
Person p = entityManager.find(Person.class, person.id);
// class org.hibernate.collection.internal.PersistentBag
System.out.println(p.phones.getClass());
entityManager.close();
factory.close();
}
@Entity(name = "Person")
public static class Person {
@Id
@GeneratedValue
private Long id;
@ElementCollection
private List<String> phones = new ArrayList<>();
public List<String> getPhones() {
return phones;
}
}
}
生成 SQL
alter table Person_phones drop constraint FKrix25kl8vxh8um4weu9l2ulnq
drop table if exists Person cascade
drop table if exists Person_phones cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Person (id int8 not null, primary key (id))
create table Person_phones (Person_id int8 not null, phones varchar(255))
alter table Person_phones add constraint FKrix25kl8vxh8um4weu9l2ulnq foreign key (Person_id) references Person
select nextval ('hibernate_sequence')
insert into Person (id) values (1)
insert into Person_phones (Person_id, phones) values (1, '123-456-7890')
insert into Person_phones (Person_id, phones) values (1, '456-000-1234')
delete from Person_phones where Person_id=1
select test_perso0_.id as id1_0_0_ from Person test_perso0_ where test_perso0_.id=1
Removing collection elements
package org.example.demo.hibernate;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Persistence;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager entityManager = factory.createEntityManager();
Person person = new Person();
person.getPhones().add("123-456-7890");
person.getPhones().add("456-000-1234");
entityManager.getTransaction().begin();
entityManager.persist(person);
entityManager.flush();
person.phones.remove(0);
entityManager.getTransaction().commit();
entityManager.clear();
entityManager.close();
factory.close();
}
@Entity(name = "Person")
public static class Person {
@Id
@GeneratedValue
private Long id;
@ElementCollection
private List<String> phones = new ArrayList<>();
public List<String> getPhones() {
return phones;
}
}
}
生成 SQL
alter table Person_phones drop constraint FKrix25kl8vxh8um4weu9l2ulnq
drop table if exists Person cascade
drop table if exists Person_phones cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Person (id int8 not null, primary key (id))
create table Person_phones (Person_id int8 not null, phones varchar(255))
alter table Person_phones add constraint FKrix25kl8vxh8um4weu9l2ulnq foreign key (Person_id) references Person
select nextval ('hibernate_sequence')
insert into Person (id) values (1)
insert into Person_phones (Person_id, phones) values (1, '123-456-7890')
insert into Person_phones (Person_id, phones) values (1, '456-000-1234')
delete from Person_phones where Person_id=1
insert into Person_phones (Person_id, phones) values (1, '456-000-1234')
Removing collection elements using the order column
package org.example.demo.hibernate;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OrderColumn;
import javax.persistence.Persistence;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager entityManager = factory.createEntityManager();
Person person = new Person();
person.getPhones().add("123-456-7890");
person.getPhones().add("456-000-1234");
entityManager.getTransaction().begin();
entityManager.persist(person);
entityManager.flush();
person.phones.remove(0);
entityManager.getTransaction().commit();
entityManager.clear();
entityManager.close();
factory.close();
}
@Entity(name = "Person")
public static class Person {
@Id
@GeneratedValue
private Long id;
@ElementCollection
@OrderColumn(name = "order_id")
private List<String> phones = new ArrayList<>();
public List<String> getPhones() {
return phones;
}
}
}
生成 SQL
alter table Person_phones drop constraint FKrix25kl8vxh8um4weu9l2ulnq
drop table if exists Person cascade
drop table if exists Person_phones cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Person (id int8 not null, primary key (id))
create table Person_phones (Person_id int8 not null, phones varchar(255), order_id int4 not null, primary key (Person_id, order_id))
alter table Person_phones add constraint FKrix25kl8vxh8um4weu9l2ulnq foreign key (Person_id) references Person
select nextval ('hibernate_sequence')
insert into Person (id) values (1)
insert into Person_phones (Person_id, order_id, phones) values (1, 0, '123-456-7890')
insert into Person_phones (Person_id, order_id, phones) values (1, 1, '456-000-1234')
delete from Person_phones where Person_id=1 and order_id=1
update Person_phones set phones='456-000-1234' where Person_id=1 and order_id=0
The @OrderColumn column works best when removing from the tail of the collection, as it only requires a single delete statement. Removing from the head or the middle of the collection requires deleting the extra elements and updating the remaining ones to preserve element order.
Embeddable type collections
package org.example.demo.hibernate;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Persistence;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager entityManager = factory.createEntityManager();
Person person = new Person();
person.getPhones().add(new Phone("landline", "028-234-9876"));
person.getPhones().add(new Phone("mobile", "072-122-9876"));
entityManager.getTransaction().begin();
entityManager.persist(person);
entityManager.flush();
person.phones.remove(0);
entityManager.getTransaction().commit();
entityManager.clear();
entityManager.close();
factory.close();
}
@Entity(name = "Person")
public static class Person {
@Id
@GeneratedValue
private Long id;
@ElementCollection
private List<Phone> phones = new ArrayList<>();
public List<Phone> getPhones() {
return phones;
}
}
@Embeddable
public static class Phone {
private String type;
@Column(name = "`number`")
private String number;
public Phone() {
}
public Phone(String type, String number) {
this.type = type;
this.number = number;
}
public String getType() {
return type;
}
public String getNumber() {
return number;
}
}
}
生成 SQL
alter table Person_phones drop constraint FKrix25kl8vxh8um4weu9l2ulnq
drop table if exists Person cascade
drop table if exists Person_phones cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Person (id int8 not null, primary key (id))
create table Person_phones (Person_id int8 not null, "number" varchar(255), type varchar(255))
alter table Person_phones add constraint FKrix25kl8vxh8um4weu9l2ulnq foreign key (Person_id) references Person
select nextval ('hibernate_sequence')
insert into Person (id) values (1)
insert into Person_phones (Person_id, "number", type) values (1, '028-234-9876', 'landline')
insert into Person_phones (Person_id, "number", type) values (1, '072-122-9876', 'mobile')
delete from Person_phones where Person_id=1
insert into Person_phones (Person_id, "number", type) values (1, '072-122-9876', 'mobile')