mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c2e9ccacd | ||
|
|
29aa395cd4 | ||
|
|
8160d1f01c | ||
|
|
6fd76ff697 |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.22.9</version>
|
||||
<version>11.22.10</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-11.22.9</tag>
|
||||
<tag>ebean-11.22.10</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
|
||||
@@ -8,7 +8,9 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class DbIdentity {
|
||||
|
||||
private static final Pattern TABLE_REPLACE = Pattern.compile("{table}", Pattern.LITERAL);
|
||||
private static final String TABLE_PLACEHOLDER = "{table}";
|
||||
|
||||
private static final Pattern TABLE_REPLACE = Pattern.compile(TABLE_PLACEHOLDER, Pattern.LITERAL);
|
||||
|
||||
/**
|
||||
* Set if this DB supports sequences. Note some DB's support both Sequences
|
||||
@@ -53,7 +55,9 @@ public class DbIdentity {
|
||||
if (selectLastInsertedIdTemplate == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!selectLastInsertedIdTemplate.contains(TABLE_PLACEHOLDER)) {
|
||||
return selectLastInsertedIdTemplate;
|
||||
}
|
||||
return TABLE_REPLACE.matcher(selectLastInsertedIdTemplate).replaceAll(Matcher.quoteReplacement(table));
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
@@ -147,6 +148,11 @@ public interface DbMigration {
|
||||
*/
|
||||
void addDatabasePlatform(DatabasePlatform databasePlatform, String prefix);
|
||||
|
||||
/**
|
||||
* Return the list of versions that contain pending drops.
|
||||
*/
|
||||
List<String> getPendingDrops();
|
||||
|
||||
/**
|
||||
* Generate the next migration xml file and associated apply and rollback sql scripts.
|
||||
* <p>
|
||||
|
||||
@@ -303,6 +303,23 @@ public class DefaultDbMigration implements DbMigration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the versions containing pending drops.
|
||||
*/
|
||||
public List<String> getPendingDrops() {
|
||||
if (!online) {
|
||||
DbOffline.setGenerateMigration();
|
||||
}
|
||||
setDefaults();
|
||||
try {
|
||||
return createRequest().getPendingDrops();
|
||||
} finally {
|
||||
if (!online) {
|
||||
DbOffline.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the configuration for each of the target platforms.
|
||||
*/
|
||||
@@ -494,6 +511,9 @@ public class DefaultDbMigration implements DbMigration {
|
||||
if (nextDrop != null) {
|
||||
return nextDrop;
|
||||
}
|
||||
if (generatePendingDrop != null) {
|
||||
return generatePendingDrop;
|
||||
}
|
||||
return migrationConfig.getGeneratePendingDrop();
|
||||
}
|
||||
|
||||
@@ -595,9 +615,6 @@ public class DefaultDbMigration implements DbMigration {
|
||||
if (name != null) {
|
||||
migrationConfig.setName(name);
|
||||
}
|
||||
if (generatePendingDrop != null) {
|
||||
migrationConfig.setGeneratePendingDrop(generatePendingDrop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1398,4 +1398,10 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
return orphanBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL used to fetch the last inserted id value.
|
||||
*/
|
||||
public String getSelectLastInsertedId() {
|
||||
return beanDescriptor.getSelectLastInsertedId(publish);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* getGeneratedKeys is not supported.
|
||||
*/
|
||||
private final String selectLastInsertedId;
|
||||
private final String selectLastInsertedIdDraft;
|
||||
|
||||
private final boolean autoTunable;
|
||||
|
||||
@@ -473,6 +474,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.sequenceInitialValue = deploy.getSequenceInitialValue();
|
||||
this.sequenceAllocationSize = deploy.getSequenceAllocationSize();
|
||||
this.selectLastInsertedId = deploy.getSelectLastInsertedId();
|
||||
this.selectLastInsertedIdDraft = deploy.getSelectLastInsertedIdDraft();
|
||||
this.concurrencyMode = deploy.getConcurrencyMode();
|
||||
this.updateChangesOnly = deploy.isUpdateChangesOnly();
|
||||
this.indexDefinitions = deploy.getIndexDefinitions();
|
||||
@@ -3086,8 +3088,15 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* supported.
|
||||
* </p>
|
||||
*/
|
||||
public String getSelectLastInsertedId() {
|
||||
return selectLastInsertedId;
|
||||
public String getSelectLastInsertedId(boolean publish) {
|
||||
return publish ? selectLastInsertedId : selectLastInsertedIdDraft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this bean uses a SQL select to fetch the last inserted id value.
|
||||
*/
|
||||
public boolean supportsSelectLastInsertedId() {
|
||||
return selectLastInsertedId != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1387,9 +1387,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
}
|
||||
|
||||
if (IdType.IDENTITY == desc.getIdType()) {
|
||||
// used when getGeneratedKeys is not supported (SQL Server 2000)
|
||||
// used when getGeneratedKeys is not supported (SQL Server 2000, SAP Hana)
|
||||
String selectLastInsertedId = dbIdentity.getSelectLastInsertedId(desc.getBaseTable());
|
||||
desc.setSelectLastInsertedId(selectLastInsertedId);
|
||||
String selectLastInsertedIdDraft = (!desc.isDraftable()) ? selectLastInsertedId : dbIdentity.getSelectLastInsertedId(desc.getDraftTable());
|
||||
desc.setSelectLastInsertedId(selectLastInsertedId, selectLastInsertedIdDraft);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ public class DeployBeanDescriptor<T> {
|
||||
* Used with Identity columns but no getGeneratedKeys support.
|
||||
*/
|
||||
private String selectLastInsertedId;
|
||||
private String selectLastInsertedIdDraft;
|
||||
|
||||
/**
|
||||
* The concurrency mode for beans of this type.
|
||||
@@ -839,11 +840,16 @@ public class DeployBeanDescriptor<T> {
|
||||
return selectLastInsertedId;
|
||||
}
|
||||
|
||||
public String getSelectLastInsertedIdDraft() {
|
||||
return selectLastInsertedIdDraft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SQL used to return the last inserted Id.
|
||||
*/
|
||||
public void setSelectLastInsertedId(String selectLastInsertedId) {
|
||||
public void setSelectLastInsertedId(String selectLastInsertedId, String selectLastInsertedIdDraft) {
|
||||
this.selectLastInsertedId = selectLastInsertedId;
|
||||
this.selectLastInsertedIdDraft = selectLastInsertedIdDraft;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,7 +39,7 @@ public class InsertHandler extends DmlHandler {
|
||||
* A SQL Select used to fetch back the Id where generatedKeys is not
|
||||
* supported.
|
||||
*/
|
||||
private String selectLastInsertedId;
|
||||
private boolean useSelectLastInsertedId;
|
||||
|
||||
/**
|
||||
* Create to handle the insert execution.
|
||||
@@ -79,7 +79,7 @@ public class InsertHandler extends DmlHandler {
|
||||
useGeneratedKeys = true;
|
||||
} else {
|
||||
// use a query to get the last inserted id
|
||||
selectLastInsertedId = meta.getSelectLastInsertedId();
|
||||
useSelectLastInsertedId = meta.supportsSelectLastInsertedId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,8 +117,7 @@ public class InsertHandler extends DmlHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the insert in a normal non batch fashion. Additionally using
|
||||
* getGeneratedKeys if required.
|
||||
* Execute non batched insert additionally using getGeneratedKeys if required.
|
||||
*/
|
||||
@Override
|
||||
public int execute() throws SQLException, OptimisticLockException {
|
||||
@@ -127,7 +126,7 @@ public class InsertHandler extends DmlHandler {
|
||||
// get the auto-increment value back and set into the bean
|
||||
getGeneratedKeys();
|
||||
|
||||
} else if (selectLastInsertedId != null) {
|
||||
} else if (useSelectLastInsertedId) {
|
||||
// fetch back the Id using a query
|
||||
fetchGeneratedKeyUsingSelect();
|
||||
}
|
||||
@@ -167,12 +166,10 @@ public class InsertHandler extends DmlHandler {
|
||||
*/
|
||||
private void fetchGeneratedKeyUsingSelect() throws SQLException {
|
||||
|
||||
Connection conn = transaction.getConnection();
|
||||
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rset = null;
|
||||
try {
|
||||
stmt = conn.prepareStatement(selectLastInsertedId);
|
||||
stmt = transaction.getConnection().prepareStatement(persistRequest.getSelectLastInsertedId());
|
||||
rset = stmt.executeQuery();
|
||||
setGeneratedKey(rset);
|
||||
} finally {
|
||||
|
||||
@@ -38,7 +38,7 @@ public final class InsertMeta {
|
||||
/**
|
||||
* Used for DB that do not support getGeneratedKeys.
|
||||
*/
|
||||
private final String selectLastInsertedId;
|
||||
private final boolean supportsSelectLastInsertedId;
|
||||
|
||||
private final Bindable shadowFKey;
|
||||
|
||||
@@ -69,7 +69,7 @@ public final class InsertMeta {
|
||||
this.sqlNullId = null;
|
||||
this.sqlDraftNullId = null;
|
||||
this.supportsGetGeneratedKeys = false;
|
||||
this.selectLastInsertedId = null;
|
||||
this.supportsSelectLastInsertedId = false;
|
||||
|
||||
} else {
|
||||
// insert sql for db identity or sequence insert
|
||||
@@ -77,11 +77,11 @@ public final class InsertMeta {
|
||||
if (id.getIdentityColumn() == null) {
|
||||
this.identityDbColumns = new String[]{};
|
||||
this.supportsGetGeneratedKeys = false;
|
||||
this.selectLastInsertedId = null;
|
||||
this.supportsSelectLastInsertedId = false;
|
||||
} else {
|
||||
this.identityDbColumns = new String[]{id.getIdentityColumn()};
|
||||
this.supportsGetGeneratedKeys = dbPlatform.getDbIdentity().isSupportsGetGeneratedKeys();
|
||||
this.selectLastInsertedId = desc.getSelectLastInsertedId();
|
||||
this.supportsSelectLastInsertedId = desc.supportsSelectLastInsertedId();
|
||||
}
|
||||
this.sqlNullId = genSql(true, tableName, false);
|
||||
this.sqlDraftNullId = desc.isDraftable() ? genSql(true, draftTableName, true) : sqlNullId;
|
||||
@@ -116,15 +116,11 @@ public final class InsertMeta {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sql that is used to fetch back the last inserted id. This will
|
||||
* return null if it should not be used.
|
||||
* <p>
|
||||
* This is only for DB's that do not support getGeneratedKeys. For MS
|
||||
* SQLServer 2000 this could return "SELECT (at)(at)IDENTITY as id".
|
||||
* </p>
|
||||
* Return true if we should use a SQL query to return the generated key.
|
||||
* This can not be used with JDBC batch mode.
|
||||
*/
|
||||
public String getSelectLastInsertedId() {
|
||||
return selectLastInsertedId;
|
||||
public boolean supportsSelectLastInsertedId() {
|
||||
return supportsSelectLastInsertedId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DbIdentity;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import org.tests.model.draftable.BasicDraftableBean;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class PlatformNoGeneratedKeysTest {
|
||||
|
||||
static EbeanServer server = testH2Server();
|
||||
|
||||
@Test
|
||||
public void insertBatch_expect_noIdValuesFetched() {
|
||||
|
||||
EBasicVer b0 = new EBasicVer("a");
|
||||
EBasicVer b1 = new EBasicVer("b");
|
||||
EBasicVer b2 = new EBasicVer("c");
|
||||
|
||||
try (Transaction transaction = server.beginTransaction()) {
|
||||
transaction.setBatchMode(true);
|
||||
|
||||
server.save(b0);
|
||||
server.save(b1);
|
||||
server.save(b2);
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
assertThat(b0.getId()).isNull();
|
||||
assertThat(b1.getId()).isNull();
|
||||
assertThat(b2.getId()).isNull();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertNoBatch_expect_selectIdentity() {
|
||||
|
||||
EBasicVer b0 = new EBasicVer("one");
|
||||
server.save(b0);
|
||||
|
||||
assertThat(b0.getId()).isNotNull();
|
||||
|
||||
|
||||
BasicDraftableBean d0 = new BasicDraftableBean("done");
|
||||
server.save(d0);
|
||||
|
||||
assertThat(d0.getId()).isNotNull();
|
||||
|
||||
server.publish(BasicDraftableBean.class, d0.getId());
|
||||
|
||||
BasicDraftableBean one = server.find(BasicDraftableBean.class, d0.getId());
|
||||
|
||||
assertThat(one.getName()).isEqualTo("done");
|
||||
assertThat(one.isDraft()).isFalse();
|
||||
}
|
||||
|
||||
private static EbeanServer testH2Server() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
config.setName("h2_noGeneratedKeys");
|
||||
|
||||
OtherH2Platform platform = new OtherH2Platform();
|
||||
DbIdentity dbIdentity = platform.getDbIdentity();
|
||||
dbIdentity.setIdType(IdType.IDENTITY);
|
||||
dbIdentity.setSupportsIdentity(true);
|
||||
dbIdentity.setSupportsGetGeneratedKeys(false);
|
||||
dbIdentity.setSupportsSequence(false);
|
||||
dbIdentity.setSelectLastInsertedIdTemplate("select identity() --{table}");
|
||||
|
||||
config.setDatabasePlatform(platform);
|
||||
config.getDataSourceConfig().setUsername("sa");
|
||||
config.getDataSourceConfig().setPassword("");
|
||||
config.getDataSourceConfig().setUrl("jdbc:h2:mem:withPCQuery;");
|
||||
config.getDataSourceConfig().setDriver("org.h2.Driver");
|
||||
|
||||
config.setDisableL2Cache(true);
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
config.setDdlGenerate(true);
|
||||
config.setDdlRun(true);
|
||||
config.getClasses().add(EBasicVer.class);
|
||||
config.getClasses().add(BasicDraftableBean.class);
|
||||
|
||||
|
||||
return EbeanServerFactory.create(config);
|
||||
}
|
||||
|
||||
static class OtherH2Platform extends H2Platform {
|
||||
|
||||
OtherH2Platform() {
|
||||
super();
|
||||
this.platform = Platform.GENERIC;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package io.ebeaninternal.dbmigration;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
@@ -13,6 +12,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.StrictAssertions.assertThatThrownBy;
|
||||
@@ -71,8 +71,11 @@ public class DbMigrationDropHistoryTest {
|
||||
assertThat(migration.generateMigration()).isNull(); // subsequent call
|
||||
|
||||
|
||||
List<String> pendingDrops = migration.getPendingDrops();
|
||||
assertThat(pendingDrops).contains("1.1");
|
||||
|
||||
System.setProperty("ddl.migration.pendingDropsFor", "1.1");
|
||||
//System.setProperty("ddl.migration.pendingDropsFor", "1.1");
|
||||
migration.setGeneratePendingDrop("1.1");
|
||||
assertThat(migration.generateMigration()).isEqualTo("1.2__dropsFor_1.1");
|
||||
assertThatThrownBy(()->migration.generateMigration())
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.tests.model.draftable;
|
||||
|
||||
import io.ebean.annotation.Draft;
|
||||
import io.ebean.annotation.Draftable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
@Draftable
|
||||
public class BasicDraftableBean extends BaseDomain {
|
||||
|
||||
private String name;
|
||||
|
||||
@Draft
|
||||
boolean draft;
|
||||
|
||||
public BasicDraftableBean(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isDraft() {
|
||||
return draft;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<ddl-script name="order views" platforms="h2" drop="true">
|
||||
drop view order_agg_vw if exists;
|
||||
</ddl-script>
|
||||
<ddl-script name="order views" platforms="generic,db2,h2,postgres,oracle,mysql">
|
||||
<ddl-script name="order views" platforms="db2,h2,postgres,oracle,mysql">
|
||||
|
||||
create or replace view order_agg_vw as
|
||||
select d.order_id, sum(d.order_qty * d.unit_price) as order_total,
|
||||
|
||||
Reference in New Issue
Block a user