Enterprise Java Development@TOPIC@
Create a JUnit test class to host tests for the one-to-many mappings.
package myorg.relex;
import static org.junit.Assert.*;
import javax.persistence.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.*;
public class One2ManyTest extends JPATestBase {
private static Log log = LogFactory.getLog(One2ManyTest.class);
@Test
public void testSample() {
log.info("testSample");
}
}
Verify the new JUnit test class builds and executes to completion
relationEx]$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest ... -HHH000401: using driver [org.h2.Driver] at URL [jdbc:h2:tcp://localhost:9092/h2db/ejava] ... [INFO] BUILD SUCCESS
package myorg.relex.one2many;
import javax.persistence.*;
/**
* This class provides an example of an entity class on the many side of a one-to-many,
* uni-directional relationship that will be referenced through a JoinTable.
*/
@Entity
@Table(name="RELATIONEX_RIDER")
public class Rider {
@Id @GeneratedValue
private int id;
@Column(length=32)
private String name;
public Rider() {}
public Rider(int id) {
this.id = id;
}
public int getId() { return id; }
public String getName() { return name; }
public void setName(String name) {
this.name = name;
}
}
package myorg.relex.one2many;
import java.util.List;
import javax.persistence.*;
/**
* This entity class provides an example of the one side of a one-to-many, uni-directional relation
* that is realized through a JoinTable.
*/
@Entity
@Table(name="RELATIONEX_BUS")
public class Bus {
@Id
private int number;
@OneToMany
// @JoinTable(
// name="RELATIONEX_BUS_RIDER",
// joinColumns={@JoinColumn(name="BUS_NO")},
// inverseJoinColumns={@JoinColumn(name="RIDER_ID")}
// )
private List<Rider> passengers;
protected Bus() {}
public Bus(int number) {
this.number = number;
}
public int getNumber() { return number; }
public List<Rider> getPassengers() {
if (passengers==null) { passengers = new ArrayList<Rider>(); }
return passengers;
}
public void setPassengers(List<Rider> passengers) {
this.passengers = passengers;
}
}
Add the two entity classes to the persistence unit.
<class>myorg.relex.one2many.Rider</class>
<class>myorg.relex.one2many.Bus</class>
$ mvn clean process-test-classes; more target/classes/ddl/relationEx-createJPA.ddl ... create table RELATIONEX_BUS ( number integer not null, primary key (number) ); create table RELATIONEX_BUS_RELATIONEX_RIDER ( RELATIONEX_BUS_number integer not null, passengers_id integer not null, unique (passengers_id) ); ... create table RELATIONEX_RIDER ( id integer generated by default as identity, name varchar(32), primary key (id) ); ... alter table RELATIONEX_BUS_RELATIONEX_RIDER add constraint FK3F295C59773EE4ED foreign key (RELATIONEX_BUS_number) references RELATIONEX_BUS; alter table RELATIONEX_BUS_RELATIONEX_RIDER add constraint FK3F295C5994D90F30 foreign key (passengers_id) references RELATIONEX_RIDER;
Fill in the relationship mapping with non-default values.
@OneToMany
@JoinTable(
name="RELATIONEX_BUS_RIDER",
joinColumns={@JoinColumn(name="BUS_NO")},
inverseJoinColumns={@JoinColumn(name="RIDER_ID")}
)
private List<Rider> passengers;
$ mvn clean process-test-classes; more target/classes/ddl/relationEx-createJPA.ddl ... create table RELATIONEX_BUS ( number integer not null, primary key (number) ); create table RELATIONEX_BUS_RIDER ( BUS_NO integer not null, RIDER_ID integer not null, unique (RIDER_ID) ); ... create table RELATIONEX_RIDER ( id integer generated by default as identity, name varchar(32), primary key (id) ); ... alter table RELATIONEX_BUS_RIDER add constraint FKE78EAB2B869BB455 foreign key (BUS_NO) references RELATIONEX_BUS; alter table RELATIONEX_BUS_RIDER add constraint FKE78EAB2B3961502F foreign key (RIDER_ID) references RELATIONEX_RIDER;
@Test
public void testOneToManyUniJoinTable() {
log.info("*** testOneToManyUniJoinTable ***");
Bus bus = new Bus(302);
em.persist(bus);
List<Rider> riders = new ArrayList<Rider>();
for (int i=0; i<2; i++) {
Rider rider = new Rider();
rider.setName("rider" + i);
em.persist(rider);
riders.add(rider);
}
log.debug("relating entities");
bus.getPassengers().addAll(riders);
em.flush(); em.clear();
log.debug("verify we have expected objects");
Bus bus2 = em.find(Bus.class, bus.getNumber());
assertNotNull("bus not found", bus2);
for (Rider r: bus.getPassengers()) {
assertNotNull("rider not found", em.find(Rider.class, r.getId()));
}
log.debug("verify they are related");
assertEquals("unexpected number of riders", bus.getPassengers().size(), bus2.getPassengers().size());
}
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniJoinTable ... -relating entities Hibernate: insert into RELATIONEX_BUS_RIDER (BUS_NO, RIDER_ID) values (?, ?) Hibernate: insert into RELATIONEX_BUS_RIDER (BUS_NO, RIDER_ID) values (?, ?)
-verify we have expected objects Hibernate: select bus0_.number as number23_0_ from RELATIONEX_BUS bus0_ where bus0_.number=?
log.debug("verify they are related");
assertEquals("unexpected number of riders", bus.getPassengers().size(), bus2.getPassengers().size());
-verify they are related Hibernate: select passengers0_.BUS_NO as BUS1_23_1_, passengers0_.RIDER_ID as RIDER2_1_, rider1_.id as id22_0_, rider1_.name as name22_0_ from RELATIONEX_BUS_RIDER passengers0_ inner join RELATIONEX_RIDER rider1_ on passengers0_.RIDER_ID=rider1_.id where passengers0_.BUS_NO=?
log.debug("remove one of the child objects");
em.remove(bus2.getPassengers().get(0)); //ouch!!! this will violate a FK-constraint
em.flush();
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniJoinTable ... -remove one of the child objects Hibernate: delete from RELATIONEX_RIDER where id=? -SQL Error: 23503, SQLState: 23503 -Referential integrity constraint violation: "FKE78EAB2B3961502F: PUBLIC.RELATIONEX_BUS_RIDER FOREIGN KEY(RIDER_ID) REFERENCES PUBLIC.RELATIONEX_RIDER(ID) (1)"; SQL statement: delete from RELATIONEX_RIDER where id=? [23503-168]
log.debug("remove one of the child objects");
Rider rider = bus2.getPassengers().get(0);
log.debug("removing the relationship");
assertTrue("ride not found in relation", bus2.getPassengers().remove(rider));
em.flush();
log.debug("removing the object");
em.remove(rider);
em.flush();
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniJoinTable ... -remove one of the child objects -removing the relationship Hibernate: delete from RELATIONEX_BUS_RIDER where BUS_NO=? Hibernate: insert into RELATIONEX_BUS_RIDER (BUS_NO, RIDER_ID) values (?, ?) -removing the object Hibernate: delete from RELATIONEX_RIDER where id=? ... [INFO] BUILD SUCCESS
package myorg.relex.one2many;
import javax.persistence.*;
/**
* This class provides an example of the many side of a one-to-many, uni-directional relationship
* mapped using a foreign key in the child entity table. Note that all mapping will be from the one/owning
* side and no reference to the foreign key exists within this class.
*/
@Entity
@Table(name="RELATIONEX_STOP")
public class Stop {
@Id @GeneratedValue
private int id;
@Column(length=16)
private String name;
public int getId() { return id; }
public String getName() { return name; }
public void setName(String name) {
this.name = name;
}
}
package myorg.relex.one2many;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
/**
* This class provides an example of the one side of a one-to-many, uni-directional relationship
* mapped using a foreign key inserted into the child/many table. The @JoinColumn is referencing
* the child table and not this entity's table.
*/
@Entity
@Table(name="RELATIONEX_ROUTE")
public class Route {
@Id
private int number;
@OneToMany
@JoinColumn
private List<Stop> stops;
protected Route() {}
public Route(int number) {
this.number = number;
}
public int getNumber() { return number; }
public List<Stop> getStops() {
if (stops == null) { stops = new ArrayList<Stop>(); }
return stops;
}
public void setStops(List<Stop> stops) {
this.stops = stops;
}
}
Add the two new entity classes to the persistence unit.
<class>myorg.relex.one2many.Stop</class>
<class>myorg.relex.one2many.Route</class>
$ mvn clean process-test-classes; more target/classes/ddl/relationEx-createJPA.ddl ... create table RELATIONEX_ROUTE ( number integer not null, primary key (number) ); ... create table RELATIONEX_STOP ( id integer generated by default as identity, name varchar(16), stops_number integer, primary key (id) ); ... alter table RELATIONEX_STOP add constraint FK35604A92586DC195 foreign key (stops_number) references RELATIONEX_ROUTE;
Add the following test method to your existig one-to-many JUnit test case.-
@Test
public void testOneToManyUniFK() {
log.info("*** testOneToManyUniFK ***");
Route route = new Route(302);
em.persist(route);
List<Stop> stops = new ArrayList<Stop>();
for (int i=0; i<2; i++) {
Stop stop = new Stop();
stop.setName("stop" + i);
em.persist(stop);
stops.add(stop);
}
log.debug("relating entities");
route.getStops().addAll(stops);
em.flush(); em.clear();
log.debug("verify we have expected objects");
Route route2 = em.find(Route.class, route.getNumber());
assertNotNull("route not found", route2);
for (Stop s: route.getStops()) {
assertNotNull("stop not found", em.find(Stop.class, s.getId()));
}
log.debug("verify they are related");
assertEquals("unexpected number of stops", route.getStops().size(), route2.getStops().size());
}
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniFK ... -relating entities Hibernate: update RELATIONEX_STOP set stops_number=? where id=? Hibernate: update RELATIONEX_STOP set stops_number=? where id=?
Notice how there is no longer a join required when obtaining a list of all children
-verify we have expected objects ... -verify they are related Hibernate: select stops0_.stops_number as stops3_25_1_, stops0_.id as id1_, stops0_.id as id24_0_, stops0_.name as name24_0_ from RELATIONEX_STOP stops0_ where stops0_.stops_number=?
log.debug("remove one of the child objects");
log.debug("removing the object and relationship");
em.remove(route2.getStops().get(0));
em.flush();
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniFK ... -remove one of the child objects -removing the object and relationship Hibernate: delete from RELATIONEX_STOP where id=? ... [INFO] BUILD SUCCESS
package myorg.relex.one2many;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
/**
* This class provides an example of the owning side of a collection of base data types.
* In this case we want a unique set of strings (aliases) mapped to this entity using
* a separate dependent table and a foreign key relationship.
*/
@Entity
@Table(name="RELATIONEX_SUSPECT")
public class Suspect {
@Id @GeneratedValue
private int id;
@Column(length=32)
private String name;
// @ElementCollection
// @CollectionTable(
// name="RELATIONEX_SUSPECT_ALIASES",
// joinColumns=@JoinColumn(name="SUSPECT_ID"),
// uniqueConstraints=@UniqueConstraint(columnNames={"SUSPECT_ID", "ALIAS"}))
// @Column(name="ALIAS", length=32)
@Lob
private Set<String> aliases;
public int getId() { return id; }
public String getName() { return name; }
public void setName(String name) {
this.name = name;
}
public Set<String> getAliases() {
if (aliases==null) { aliases = new HashSet<String>(); }
return aliases;
}
public void setAliases(Set<String> aliases) {
this.aliases = aliases;
}
}
Add the new entity class to the persistence unit
<class>myorg.relex.one2many.Suspect</class>
$ mvn clean process-test-classes; more target/classes/ddl/relationEx-createJPA.ddl ... create table RELATIONEX_SUSPECT ( id integer generated by default as identity, aliases blob, name varchar(32), primary key (id) );
@ElementCollection // @CollectionTable( // name="RELATIONEX_SUSPECT_ALIASES", // joinColumns=@JoinColumn(name="SUSPECT_ID"), // uniqueConstraints=@UniqueConstraint(columnNames={"SUSPECT_ID", "ALIAS"})) // @Column(name="ALIAS", length=32) private Set<String> aliases;
Rebuild the module and observe the new database schema generated.
$ mvn clean process-test-classes; more target/classes/ddl/relationEx-createJPA.ddl ... create table RELATIONEX_SUSPECT ( id integer generated by default as identity, name varchar(32), primary key (id) ); ... create table Suspect_aliases ( Suspect_id integer not null, aliases varchar(255) ); ... alter table Suspect_aliases add constraint FK9AC56596DE29C9CF foreign key (Suspect_id) references RELATIONEX_SUSPECT;
Update the table mapping to control the table and column properties of the child table.
@ElementCollection
@CollectionTable(
name="RELATIONEX_SUSPECT_ALIASES",
joinColumns=@JoinColumn(name="SUSPECT_ID"),
uniqueConstraints=@UniqueConstraint(columnNames={"SUSPECT_ID", "ALIAS"}))
@Column(name="ALIAS", length=32)
private Set<String> aliases;
Rebuild the module and notice the change in database schema generated.
$ mvn clean process-test-classes; more target/classes/ddl/relationEx-createJPA.ddl ... create table RELATIONEX_SUSPECT ( id integer generated by default as identity, name varchar(32), primary key (id) ); create table RELATIONEX_SUSPECT_ALIASES ( SUSPECT_ID integer not null, ALIAS varchar(32), unique (SUSPECT_ID, ALIAS) ); ... alter table RELATIONEX_SUSPECT_ALIASES add constraint FK3FD160E6DE29C9CF foreign key (SUSPECT_ID) references RELATIONEX_SUSPECT;
@ColumnTable.name was used to name the dependent/child table
@ColumnTable.joinColumns was used to name the foreign key to the parent table
@ColumnTable.uniqueConstraints was used to restrict columns in table to unique values
@Column.name was used to name the value column used to hold the member of collection
@Column.length was used to control the size of the value column
@Test
public void testOneToManyUniElementCollection() {
log.info("*** testOneToManyUniElementCollection ***");
Suspect suspect = new Suspect();
suspect.setName("william");
em.persist(suspect);
suspect.getAliases().add("bill");
suspect.getAliases().add("billy");
em.flush(); em.clear();
log.debug("verify we have expected objects");
Suspect suspect2 = em.find(Suspect.class, suspect.getId());
assertNotNull("suspect not found", suspect2);
for (String a: suspect.getAliases()) {
assertNotNull("alias not found", suspect2.getAliases().contains(a));
}
}
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniElementCollection ... -*** testOneToManyUniElementCollection *** Hibernate: insert into RELATIONEX_SUSPECT (id, name) values (null, ?) Hibernate: insert into RELATIONEX_SUSPECT_ALIASES (SUSPECT_ID, ALIAS) values (?, ?) Hibernate: insert into RELATIONEX_SUSPECT_ALIASES (SUSPECT_ID, ALIAS) values (?, ?)
-verify we have expected objects Hibernate: select suspect0_.id as id26_0_, suspect0_.name as name26_0_ from RELATIONEX_SUSPECT suspect0_ where suspect0_.id=? Hibernate: select aliases0_.SUSPECT_ID as SUSPECT1_26_0_, aliases0_.ALIAS as ALIAS0_ from RELATIONEX_SUSPECT_ALIASES aliases0_ where aliases0_.SUSPECT_ID=?
log.debug("remove one of the child objects");
String alias = suspect2.getAliases().iterator().next();
assertTrue("alias not found", suspect2.getAliases().remove(alias));
em.flush();
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniElementCollection ... -remove one of the child objects Hibernate: delete from RELATIONEX_SUSPECT_ALIASES where SUSPECT_ID=? and ALIAS=? ... [INFO] BUILD SUCCESS
package myorg.relex.one2many;
import java.util.Date;
import javax.persistence.*;
/**
* This class is an example of a non-entity class that will be mapped to a dependent table
* and form the many side of an @ElementCollection.
*/
@Embeddable
public class Produce {
public static enum Color { RED, GREEN, YELLOW }
@Column(length=16)
private String name;
@Enumerated(EnumType.STRING)
@Column(length=10)
private Color color;
@Temporal(TemporalType.DATE)
private Date expires;
public Produce() {}
public Produce(String name, Color color, Date expires) {
this.name = name;
this.color = color;
this.expires = expires;
}
public String getName() { return name; }
public Color getColor() { return color; }
public Date getExpires() { return expires; }
}
package myorg.relex.one2many;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
/**
* This entity class provides an example of mapping a collection of non-entity/embeddable class instances
* to a dependent/child table and relating the child table to this entity table using a foreign key.
*/
@Entity
@Table(name="RELATIONEX_BASKET")
public class Basket {
@Id @GeneratedValue
private int id;
@ElementCollection
@CollectionTable(
name="RELATIONEX_BASKET_PRODUCE",
joinColumns=@JoinColumn(name="BASKET_ID"))
// @AttributeOverrides({
// @AttributeOverride(name="name", column=@Column(name="ITEM_NAME")),
// @AttributeOverride(name="color", column=@Column(name="ITEM_COLOR"))
// })
private List<Produce> contents;
@Column(length=16)
private String name;
public int getId() { return id; }
public List<Produce> getContents() {
if (contents == null) { contents = new ArrayList<Produce>(); }
return contents;
}
public void setContents(List<Produce> contents) {
this.contents = contents;
}
public String getName() { return name; }
public void setName(String name) {
this.name = name;
}
}
Add the two entity classes to the persistence unit.
<class>myorg.relex.one2many.Basket</class>
<class>myorg.relex.one2many.Produce</class>
$ mvn clean process-test-classes; more target/classes/ddl/relationEx-createJPA.ddl ... create table RELATIONEX_BASKET ( id integer generated by default as identity, name varchar(16), primary key (id) ); create table RELATIONEX_BASKET_PRODUCE ( BASKET_ID integer not null, color varchar(10), expires date, name varchar(16) ); ... alter table RELATIONEX_BASKET_PRODUCE add constraint FKA97DDDD776CDC1E5 foreign key (BASKET_ID) references RELATIONEX_BASKET;
@ElementCollection
@CollectionTable(
name="RELATIONEX_BASKET_PRODUCE",
joinColumns=@JoinColumn(name="BASKET_ID"))
@AttributeOverrides({
@AttributeOverride(name="name", column=@Column(name="ITEM_NAME")),
@AttributeOverride(name="color", column=@Column(name="ITEM_COLOR"))
})
private List<Produce> contents;
$ mvn clean process-test-classes; more target/classes/ddl/relationEx-createJPA.ddl ... create table RELATIONEX_BASKET ( id integer generated by default as identity, name varchar(16), primary key (id) ); create table RELATIONEX_BASKET_PRODUCE ( BASKET_ID integer not null, ITEM_COLOR varchar(255), expires date, ITEM_NAME varchar(255) ); ... alter table RELATIONEX_BASKET_PRODUCE add constraint FKA97DDDD776CDC1E5 foreign key (BASKET_ID) references RELATIONEX_BASKET;
Add the following test method to your existing one-to-many JUnit test case.
@Test
public void testOneToManyUniEmbeddableElementCollection() {
log.info("*** testOneToManyUniEmbeddableElementCollection ***");
Basket basket = new Basket();
basket.setName("assorted fruit");
em.persist(basket);
basket.getContents().add(new Produce("apple", Produce.Color.RED, new Date(System.currentTimeMillis()+(3600000*24*30))));
basket.getContents().add(new Produce("banana", Produce.Color.YELLOW, new Date(System.currentTimeMillis()+(3600000*24*14))));
em.flush(); em.clear();
log.debug("verify we have expected objects");
Basket basket2 = em.find(Basket.class, basket.getId());
assertNotNull("basket not found", basket2);
assertEquals("unexpected contents", basket.getContents().size(), basket2.getContents().size());
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniEmbeddableElementCollection ... -*** testOneToManyUniEmbeddableElementCollection *** Hibernate: insert into RELATIONEX_BASKET (id, name) values (null, ?) Hibernate: insert into RELATIONEX_BASKET_PRODUCE (BASKET_ID, ITEM_COLOR, expires, ITEM_NAME) values (?, ?, ?, ?) Hibernate: insert into RELATIONEX_BASKET_PRODUCE (BASKET_ID, ITEM_COLOR, expires, ITEM_NAME) values (?, ?, ?, ?)
-verify we have expected objects Hibernate: select basket0_.id as id27_0_, basket0_.name as name27_0_ from RELATIONEX_BASKET basket0_ where basket0_.id=? Hibernate: select contents0_.BASKET_ID as BASKET1_27_0_, contents0_.ITEM_COLOR as ITEM2_0_, contents0_.expires as expires0_, contents0_.ITEM_NAME as ITEM4_0_ from RELATIONEX_BASKET_PRODUCE contents0_ where contents0_.BASKET_ID=?
log.debug("remove one of the child objects");
Produce produce = basket2.getContents().get(0);
assertTrue("produce not found", basket2.getContents().remove(produce));
em.flush();
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniEmbeddableElementCollection ... -remove one of the child objects Hibernate: delete from RELATIONEX_BASKET_PRODUCE where BASKET_ID=? Hibernate: insert into RELATIONEX_BASKET_PRODUCE (BASKET_ID, ITEM_COLOR, expires, ITEM_NAME) values (?, ?, ?, ?) ... [INFO] BUILD SUCCESS
package myorg.relex.one2many;
import javax.persistence.*;
/**
* This class is an example of the many side of a one-to-many, uni-directional relationship
* which uses orphanRemoval of target entities on the many side. This entity exists for the
* sole use of the one side of the relation.
*/
@Entity
@Table(name="RELATIONEX_TODO")
public class Todo {
@Id @GeneratedValue
private int id;
@Column(length=32)
private String title;
public Todo() {}
public Todo(String title) {
this.title = title;
}
public int getId() { return id; }
public String getTitle() { return title; }
public void setTitle(String title) {
this.title = title;
}
}
package myorg.relex.one2many; import java.util.ArrayList; import java.util.List; import javax.persistence.*; /** * This class provides an example owning entity in a one-to-many, uni-directional relationship * where the members of the collection are subject to orphanRemoval when they are removed from the * collection. */ @Entity @Table(name="RELATIONEX_TODOLIST") public class TodoList { @Id @GeneratedValue private int id; @OneToMany(cascade={CascadeType.PERSIST} // ,orphanRemoval=true ) @JoinColumn private List<Todo> todos; public int getId() { return id; } public List<Todo> getTodos() { if (todos==null) { todos = new ArrayList<Todo>(); } return todos; } public void setTodos(List<Todo> todos) { this.todos = todos; } }
Add the new entity classes to your persistence unit.
<class>myorg.relex.one2many.Todo</class>
<class>myorg.relex.one2many.TodoList</class>
@Test
public void testOneToManyUniOrphanRemoval() {
log.info("*** testOneToManyUniEmbeddableElementCollection ***");
//check how many child entities exist to start with
int startCount = em.createQuery("select count(t) from Todo t", Number.class).getSingleResult().intValue();
log.debug("create new TODO list with first entry");
TodoList list = new TodoList();
list.getTodos().add(new Todo("get up"));
em.persist(list);
em.flush();
}
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniOrphanRemoval ... -*** testOneToManyUniEmbeddableElementCollection *** Hibernate: select count(todo0_.id) as col_0_0_ from RELATIONEX_TODO todo0_ limit ? -create new TODO list with first entry Hibernate: insert into RELATIONEX_TODOLIST (id) values (null) Hibernate: insert into RELATIONEX_TODO (id, title) values (null, ?) Hibernate: update RELATIONEX_TODO set todos_id=? where id=? ... [INFO] BUILD SUCCESS
Add the following lines to the unit test to verify a child instance was created.
log.debug("verifying we have new child entity");
assertEquals("new child not found", startCount +1,
em.createQuery("select count(t) from Todo t", Number.class).getSingleResult().intValue());
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniOrphanRemoval ... -verifying we have new child entity Hibernate: select count(todo0_.id) as col_0_0_ from RELATIONEX_TODO todo0_ limit ? ... [INFO] BUILD SUCCESS
log.debug("removing child from list");
list.getTodos().clear();
em.flush();
assertEquals("orphaned child not deleted", startCount,
em.createQuery("select count(t) from Todo t", Number.class).getSingleResult().intValue());
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniOrphanRemoval ... -removing child from list Hibernate: update RELATIONEX_TODO set todos_id=null where todos_id=? Hibernate: select count(todo0_.id) as col_0_0_ from RELATIONEX_TODO todo0_ limit ? ... Failed tests: testOneToManyUniOrphanRemoval(myorg.relex.One2ManyTest): orphaned child not deleted expected:<0> but was:<1> ... [INFO] BUILD FAILURE
Enable orphanRemoval on the relationship on the parent side.
@OneToMany(cascade={CascadeType.PERSIST}
,orphanRemoval=true
)
@JoinColumn
private List<Todo> todos;
$ mvn clean test -P\!h2db -Ph2srv -Dtest=myorg.relex.One2ManyTest#testOneToManyUniOrphanRemoval ... -removing child from list Hibernate: update RELATIONEX_TODO set todos_id=null where todos_id=? Hibernate: delete from RELATIONEX_TODO where id=? Hibernate: select count(todo0_.id) as col_0_0_ from RELATIONEX_TODO todo0_ limit ? ... [INFO] BUILD SUCCESS