mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
406 lines
15 KiB
Java
406 lines
15 KiB
Java
package org.tests.merge;
|
|
|
|
import io.ebean.BaseTestCase;
|
|
import io.ebean.Ebean;
|
|
import io.ebean.FetchPath;
|
|
import io.ebean.MergeOptions;
|
|
import io.ebean.MergeOptionsBuilder;
|
|
import io.ebean.text.PathProperties;
|
|
import org.ebeantest.LoggedSqlCollector;
|
|
import org.junit.Test;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Random;
|
|
import java.util.UUID;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
public class TestMergeCustomer extends BaseTestCase {
|
|
|
|
private Random random = new Random();
|
|
|
|
@Test
|
|
public void customerOnly_defaultOptions_expect_updateOnly() {
|
|
|
|
MCustomer mCustomer = partial("cust1", "(id,name,version)");
|
|
mCustomer.setName("NotCust0");
|
|
|
|
LoggedSqlCollector.start();
|
|
|
|
Ebean.merge(mCustomer);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
assertThat(sql).hasSize(1);
|
|
assertSql(sql.get(0)).contains("update mcustomer set name=?, version=? where id=? and version=?");
|
|
}
|
|
|
|
/**
|
|
* So this is effectively the same as a stateless update.
|
|
*/
|
|
@Test
|
|
public void customerOnly_expect_updateOnly() {
|
|
|
|
|
|
MCustomer mCustomer = partial("cust1", "(id,name,version)");
|
|
mCustomer.setName("NotCust1");
|
|
|
|
MergeOptions options = new MergeOptionsBuilder().build();
|
|
|
|
|
|
LoggedSqlCollector.start();
|
|
|
|
Ebean.merge(mCustomer, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
assertThat(sql).hasSize(1);
|
|
assertSql(sql.get(0)).contains("update mcustomer set name=?, version=? where id=? and version=?");
|
|
}
|
|
|
|
@Test
|
|
public void customerOnly_setClientGeneratedIds_expect_selectAndUpdate() {
|
|
|
|
|
|
MCustomer mCustomer = partial("cust2", "(id,name,version)");
|
|
mCustomer.setName("NotCust2");
|
|
|
|
MergeOptions options = new MergeOptionsBuilder().setClientGeneratedIds().build();
|
|
|
|
LoggedSqlCollector.start();
|
|
|
|
server().merge(mCustomer, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
assertThat(sql).hasSize(2);
|
|
assertSql(sql.get(0)).contains("select t0.id from mcustomer t0 where t0.id = ?");
|
|
assertSql(sql.get(1)).contains("update mcustomer set name=?, version=? where id=? and version=?");
|
|
}
|
|
|
|
@Test
|
|
public void customerWithAddresses_setClientGeneratedIds_expect_selectAndUpdate() {
|
|
|
|
MCustomer mCustomer = partial("cust3", "(id,name,version,shippingAddress(*),billingAddress(*))");
|
|
mCustomer.setName("NotCust3");
|
|
mCustomer.getBillingAddress().setStreet("modBillStreet");
|
|
mCustomer.getShippingAddress().setCity("modShipCity");
|
|
|
|
MergeOptions options = new MergeOptionsBuilder()
|
|
.addPath("shippingAddress")
|
|
.addPath("billingAddress")
|
|
.setClientGeneratedIds()
|
|
.build();
|
|
|
|
LoggedSqlCollector.start();
|
|
|
|
server().merge(mCustomer, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
assertThat(sql).hasSize(5);
|
|
assertSql(sql.get(0)).contains("select t0.id, t2.id, t1.id from mcustomer t0 left join maddress t2 on t2.id = t0.shipping_address_id left join maddress t1 on t1.id = t0.billing_address_id where t0.id = ?");
|
|
assertSql(sql.get(1)).contains("update maddress set street=?, city=?, version=? where id=? and version=?");
|
|
assertSqlBind(sql, 2, 3);
|
|
assertThat(sql.get(4)).contains("update mcustomer set name=?, version=?, shipping_address_id=?, billing_address_id=? where id=? and version=?");
|
|
}
|
|
|
|
@Test
|
|
public void customerWithAddresses_newAddress_setClientGeneratedIds_expect_insertAddress() {
|
|
|
|
|
|
MCustomer mCustomer = partial("cust3", "(id,name,version,shippingAddress(*),billingAddress(*))");
|
|
mCustomer.setName("NotCust3");
|
|
|
|
// new billing address - no Id value so must be insert
|
|
mCustomer.setBillingAddress(new MAddress("Short", "Mid Wicket"));
|
|
mCustomer.getShippingAddress().setCity("modShipCity");
|
|
|
|
MergeOptions options = new MergeOptionsBuilder()
|
|
.addPath("shippingAddress")
|
|
.addPath("billingAddress")
|
|
.setClientGeneratedIds()
|
|
.build();
|
|
|
|
LoggedSqlCollector.start();
|
|
|
|
server().merge(mCustomer, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
assertThat(sql).hasSize(6);
|
|
assertSql(sql.get(0)).contains("select t0.id, t2.id, t1.id from mcustomer t0 left join maddress t2 on t2.id = t0.shipping_address_id left join maddress t1 on t1.id = t0.billing_address_id where t0.id = ?");
|
|
assertSql(sql.get(1)).contains("insert into maddress (id, street, city, version) values (?,?,?,?)");
|
|
assertSqlBind(sql.get(2));
|
|
assertThat(sql.get(3)).contains("update maddress set street=?, city=?, version=? where id=? and version=?");
|
|
assertSqlBind(sql.get(4));
|
|
assertThat(sql.get(5)).contains("update mcustomer set name=?, version=?, shipping_address_id=?, billing_address_id=? where id=? and version=?");
|
|
}
|
|
|
|
@Test
|
|
public void customerWithAddresses_newAddressWithId_setClientGeneratedIds_expect_additionalCheckForAddressInsert() {
|
|
|
|
|
|
MCustomer mCustomer = partial("cust3", "(id,name,version,shippingAddress(*),billingAddress(*))");
|
|
mCustomer.setName("NotCust3");
|
|
|
|
// new billing address - has Id value + setClientGeneratedIds ... so extra query to check
|
|
MAddress mAddress = new MAddress("Short", "Mid Wicket");
|
|
mAddress.setId(UUID.randomUUID());
|
|
mCustomer.setBillingAddress(mAddress);
|
|
mCustomer.getShippingAddress().setCity("modShipCity");
|
|
|
|
MergeOptions options = new MergeOptionsBuilder()
|
|
.addPath("shippingAddress")
|
|
.addPath("billingAddress")
|
|
.setClientGeneratedIds() // As we are using clientIds ... we don't know if the new UUID is an insert or update without checking
|
|
.build();
|
|
|
|
LoggedSqlCollector.start();
|
|
|
|
server().merge(mCustomer, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
assertThat(sql).hasSize(7);
|
|
assertSql(sql.get(0)).contains("select t0.id, t2.id, t1.id from mcustomer t0 left join maddress t2 on t2.id = t0.shipping_address_id left join maddress t1 on t1.id = t0.billing_address_id where t0.id = ?");
|
|
|
|
// Additional check to see if the address with the unknown UUID is 'insert' or 'update'
|
|
assertSql(sql.get(1)).contains("select t0.id from maddress t0 where t0.id = ?");
|
|
assertSql(sql.get(2)).contains("insert into maddress (id, street, city, version) values (?,?,?,?)");
|
|
assertSqlBind(sql.get(3));
|
|
assertThat(sql.get(4)).contains("update maddress set street=?, city=?, version=? where id=? and version=?");
|
|
assertSqlBind(sql.get(5));
|
|
assertThat(sql.get(6)).contains("update mcustomer set name=?, version=?, shipping_address_id=?, billing_address_id=? where id=? and version=?");
|
|
}
|
|
|
|
@Test
|
|
public void assocOne_onlineIsNull() {
|
|
|
|
MCustomer c = new MCustomer("Null Address");
|
|
c.setBillingAddress(new MAddress("Cow corner", "Mid Wicket"));
|
|
|
|
Ebean.save(c);
|
|
|
|
MCustomer mCustomer = rebuildViaJson(c);
|
|
|
|
MAddress mAddress = new MAddress("Silly", "Mid Wicket");
|
|
mAddress.setId(UUID.randomUUID());
|
|
mCustomer.setShippingAddress(mAddress);
|
|
|
|
MergeOptions options = new MergeOptionsBuilder()
|
|
.addPath("shippingAddress")
|
|
.addPath("billingAddress")
|
|
.setClientGeneratedIds()
|
|
.build();
|
|
|
|
Ebean.merge(mCustomer, options);
|
|
|
|
}
|
|
|
|
private MCustomer rebuildViaJson(MCustomer input) {
|
|
String asJson = Ebean.json().toJson(input);
|
|
return Ebean.json().toBean(MCustomer.class, asJson);
|
|
}
|
|
|
|
@Test
|
|
public void whenContacts_isNull_expect_deleteContacts() {
|
|
|
|
MCustomer mCustomer = partial("cust6", "(id,name,version,shippingAddress(id),billingAddress(id),contacts(*))");
|
|
|
|
// null contacts ... but in path so this means - delete all contacts
|
|
mCustomer.setContacts(null);
|
|
|
|
MergeOptions options = new MergeOptionsBuilder()
|
|
.addPath("contacts")
|
|
.build();
|
|
|
|
LoggedSqlCollector.start();
|
|
server().merge(mCustomer, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
if (isPersistBatchOnCascade()) {
|
|
assertThat(sql).hasSize(20);
|
|
}
|
|
assertSql(sql.get(0)).contains("select t0.id, t1.id from mcustomer t0 left join mcontact t1 on t1.customer_id = t0.id where t0.id = ?");
|
|
assertSql(sql.get(1)).contains("delete from mcontact_message where contact_id = ?");
|
|
assertThat(sql.get(3)).contains("delete from mcontact where id=?");
|
|
assertThat(sql.get(19)).contains("update mcustomer set name=?, version=?, shipping_address_id=?, billing_address_id=? where id=? and version=?");
|
|
}
|
|
|
|
|
|
@Test
|
|
public void whenContacts_isEmpty_expect_deleteContacts() {
|
|
|
|
MCustomer mCustomer = partial("cust6", "(id,name,version,shippingAddress(id),billingAddress(id),contacts(*))");
|
|
|
|
// empty contacts ... but in path so this means - delete all contacts
|
|
mCustomer.setContacts(new ArrayList<>());
|
|
|
|
MergeOptions options = new MergeOptionsBuilder()
|
|
.addPath("contacts")
|
|
.build();
|
|
|
|
LoggedSqlCollector.start();
|
|
server().merge(mCustomer, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
if (isPersistBatchOnCascade()) {
|
|
assertThat(sql).hasSize(20);
|
|
}
|
|
assertSql(sql.get(0)).contains("select t0.id, t1.id from mcustomer t0 left join mcontact t1 on t1.customer_id = t0.id where t0.id = ?");
|
|
assertSql(sql.get(1)).contains("delete from mcontact_message where contact_id = ?");
|
|
assertThat(sql.get(3)).contains("delete from mcontact where id=?");
|
|
assertThat(sql.get(19)).contains("update mcustomer set name=?, version=?, shipping_address_id=?, billing_address_id=? where id=? and version=?");
|
|
}
|
|
|
|
@Test
|
|
public void whenContacts_mixed_expect_deleteInsertUpdateContacts() {
|
|
|
|
MCustomer mCustomer = partial("cust6", "(id,name,version,shippingAddress(id),billingAddress(id),contacts(*))");
|
|
List<MContact> contacts = mCustomer.getContacts();
|
|
|
|
MContact mContact = new MContact("z@a.com", "z", "zed");
|
|
mContact.setId(UUID.randomUUID());
|
|
|
|
contacts.add(mContact);
|
|
|
|
contacts.get(0).setEmail("a@beta.com");
|
|
contacts.get(1).setEmail("b@beta.com");
|
|
contacts.remove(4);
|
|
contacts.remove(2);
|
|
|
|
MContact mContactEnd = new MContact("z@z.com", "zx", "zedXtra");
|
|
mContactEnd.setId(UUID.randomUUID());
|
|
contacts.add(mContactEnd);
|
|
|
|
|
|
MergeOptions options = new MergeOptionsBuilder()
|
|
.addPath("contacts")
|
|
.build();
|
|
|
|
LoggedSqlCollector.start();
|
|
server().merge(mCustomer, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
if (isPersistBatchOnCascade()) {
|
|
assertThat(sql).hasSize(16);
|
|
assertSql(sql.get(0)).contains("select t0.id, t1.id from mcustomer t0 left join mcontact t1 on t1.customer_id = t0.id where t0.id = ?");
|
|
assertSql(sql.get(1)).contains("delete from mcontact_message where contact_id = ?");
|
|
assertThat(sql.get(3)).contains("delete from mcontact where id=?");
|
|
assertThat(sql.get(7)).contains("update mcustomer set name=?, version=?, shipping_address_id=?, billing_address_id=? where id=? and version=?");
|
|
}
|
|
|
|
if (isPersistBatchOnCascade()) {
|
|
assertThat(sql.get(8)).contains("insert into mcontact");
|
|
assertThat(sql.get(9)).contains("-- bind(");
|
|
assertThat(sql.get(11)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
|
} else {
|
|
assertThat(sql.get(6)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
|
assertThat(sql.get(7)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
|
assertThat(sql.get(10)).contains("insert into mcontact");
|
|
assertThat(sql.get(11)).contains("insert into mcontact");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void fullMonty() {
|
|
|
|
MCustomer cust1 = customer("monty1");
|
|
|
|
modify(cust1);
|
|
|
|
MergeOptions options = new MergeOptionsBuilder()
|
|
.addPath("billingAddress")
|
|
.addPath("shippingAddress")
|
|
.addPath("contacts")
|
|
.addPath("contacts.messages")
|
|
.setClientGeneratedIds()
|
|
.setDeletePermanent()
|
|
.build();
|
|
|
|
LoggedSqlCollector.start();
|
|
server().merge(cust1, options);
|
|
|
|
List<String> sql = LoggedSqlCollector.stop();
|
|
if (isPersistBatchOnCascade()) {
|
|
|
|
assertSql(sql.get(0)).contains("select t0.id, t3.id, t1.id, t2.id from mcustomer t0 left join maddress t3 on t3.id = t0.shipping_address_id left join maddress t1 on t1.id = t0.billing_address_id left join mcontact t2 on t2.customer_id = t0.id where t0.id = ?");
|
|
if (isH2() || isHana()) {
|
|
// with nested OneToMany .. we need a second query to read the contact message ids
|
|
assertSql(sql.get(1)).contains("select t0.contact_id, t0.id from mcontact_message t0 where (t0.contact_id) in (?,?,?,?,?,?,?,?,?,?)");
|
|
}
|
|
assertSql(sql.get(2)).contains("delete from mcontact_message where contact_id = ?");
|
|
assertThat(sql.get(4)).contains("delete from mcontact where id=?");
|
|
assertThat(sql.get(5)).contains("delete from mcontact_message where contact_id = ?");
|
|
assertThat(sql.get(7)).contains("delete from mcontact where id=?");
|
|
|
|
assertThat(sql.get(8)).contains("update maddress set street=?, city=?, version=? where id=? and version=?");
|
|
assertThat(sql.get(13)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
|
assertSqlBind(sql, 14, 17);
|
|
assertThat(sql.get(18)).contains("update mcontact_message set title=?, subject=?, notes=?, version=?, contact_id=? where id=? and version=?");
|
|
assertSqlBind(sql, 19, 22);
|
|
}
|
|
}
|
|
|
|
private void modify(MCustomer cust) {
|
|
|
|
List<MContact> contacts = cust.getContacts();
|
|
MContact mContact = new MContact("z@a.com", "z", "zed");
|
|
mContact.setId(UUID.randomUUID());
|
|
|
|
contacts.add(mContact);
|
|
|
|
contacts.get(0).setEmail("a@beta.com");
|
|
contacts.get(1).setEmail("b@beta.com");
|
|
contacts.remove(4);
|
|
contacts.remove(2);
|
|
|
|
cust.setName(cust.getName()+" modified");
|
|
cust.getBillingAddress().setStreet("Short");
|
|
|
|
MAddress mAddress = new MAddress("Broken", "Dreams");
|
|
mAddress.setId(UUID.randomUUID());
|
|
cust.setShippingAddress(null);
|
|
}
|
|
|
|
private MCustomer partial(String name, String fetchGraph) {
|
|
MCustomer cust1 = buildCustomer(name);
|
|
Ebean.save(cust1);
|
|
|
|
FetchPath fetchPath = PathProperties.parse(fetchGraph);
|
|
String asJson = Ebean.json().toJson(cust1, fetchPath);
|
|
return Ebean.json().toBean(MCustomer.class, asJson);
|
|
}
|
|
|
|
private MCustomer customer(String name) {
|
|
|
|
MCustomer cust1 = buildCustomer(name);
|
|
Ebean.save(cust1);
|
|
|
|
String asJson = Ebean.json().toJson(cust1);
|
|
|
|
return Ebean.json().toBean(MCustomer.class, asJson);
|
|
}
|
|
|
|
private MCustomer buildCustomer(String name) {
|
|
|
|
MCustomer c = new MCustomer(name);
|
|
c.setShippingAddress(new MAddress("Fleet st", "London"));
|
|
c.setBillingAddress(new MAddress("Cow corner", "Mid Wicket"));
|
|
|
|
c.getContacts().add(addContact("a@a.com", "a", "alligator"));
|
|
c.getContacts().add(addContact("b@a.com", "b", "beaver"));
|
|
c.getContacts().add(addContact("c@a.com", "c", "crow"));
|
|
c.getContacts().add(addContact("d@a.com", "d", "dog"));
|
|
c.getContacts().add(addContact("e@a.com", "e", "ent"));
|
|
c.getContacts().add(addContact("f@a.com", "f", "frog"));
|
|
|
|
return c;
|
|
}
|
|
|
|
private MContact addContact(String email, String first, String last) {
|
|
MContact mContact = new MContact(email, first, last);
|
|
int i = 1 + random.nextInt(2);
|
|
for (int j = 0; j < i; j++) {
|
|
mContact.getMessages().add(new MContactMessage(first+" "+i, last+" "+i));
|
|
}
|
|
return mContact;
|
|
}
|
|
}
|