mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c1c144af5 | ||
|
|
7809858634 | ||
|
|
bd3cb3c547 | ||
|
|
db25cb7bfb | ||
|
|
55a9ba7170 | ||
|
|
2df2224286 | ||
|
|
e1e8092144 | ||
|
|
4d4886d808 | ||
|
|
d11bb2c4e5 | ||
|
|
663b1bb4aa | ||
|
|
f3d26e32ec | ||
|
|
5f83584315 |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.22.1</version>
|
||||
<version>11.22.4</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.1</tag>
|
||||
<tag>ebean-11.22.4</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
|
||||
@@ -184,13 +184,12 @@ public class ModelContainer {
|
||||
/**
|
||||
* Unset the withHistory flag on the associated base table.
|
||||
*/
|
||||
private void applyChange(DropHistoryTable change) {
|
||||
protected void applyChange(DropHistoryTable change) {
|
||||
|
||||
MTable table = tables.get(change.getBaseTable());
|
||||
if (table == null) {
|
||||
throw new IllegalStateException("Table [" + change.getBaseTable() + "] does not exist in model?");
|
||||
if (table != null) {
|
||||
table.setWithHistory(false);
|
||||
}
|
||||
table.setWithHistory(false);
|
||||
}
|
||||
|
||||
private void applyChange(AddUniqueConstraint change) {
|
||||
@@ -241,19 +240,14 @@ public class ModelContainer {
|
||||
if (tables.containsKey(tableName)) {
|
||||
throw new IllegalStateException("Table [" + tableName + "] already exists in model?");
|
||||
}
|
||||
MTable table = new MTable(createTable);
|
||||
tables.put(tableName, table);
|
||||
tables.put(tableName, new MTable(createTable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a DropTable change to the model.
|
||||
*/
|
||||
protected void applyChange(DropTable dropTable) {
|
||||
String tableName = dropTable.getName();
|
||||
if (!tables.containsKey(tableName)) {
|
||||
throw new IllegalStateException("Table [" + tableName + "] does not exists in model?");
|
||||
}
|
||||
tables.remove(tableName);
|
||||
tables.remove(dropTable.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,22 +258,16 @@ public class ModelContainer {
|
||||
if (indexes.containsKey(indexName)) {
|
||||
throw new IllegalStateException("Index [" + indexName + "] already exists in model?");
|
||||
}
|
||||
MIndex index = new MIndex(createIndex);
|
||||
indexes.put(createIndex.getIndexName(), index);
|
||||
indexes.put(createIndex.getIndexName(), new MIndex(createIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a DropTable change to the model.
|
||||
*/
|
||||
protected void applyChange(DropIndex dropIndex) {
|
||||
String name = dropIndex.getIndexName();
|
||||
if (!indexes.containsKey(name)) {
|
||||
throw new IllegalStateException("Index [" + name + "] does not exist in model?");
|
||||
}
|
||||
indexes.remove(name);
|
||||
indexes.remove(dropIndex.getIndexName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply a AddColumn change to the model.
|
||||
*/
|
||||
|
||||
@@ -7,8 +7,14 @@ import io.ebeaninternal.server.query.SqlJoinType;
|
||||
*/
|
||||
class AssocOneHelpRefExported extends AssocOneHelp {
|
||||
|
||||
public AssocOneHelpRefExported(BeanPropertyAssocOne<?> property) {
|
||||
private final boolean softDelete;
|
||||
|
||||
private final String softDeletePredicate;
|
||||
|
||||
AssocOneHelpRefExported(BeanPropertyAssocOne<?> property) {
|
||||
super(property);
|
||||
this.softDelete = property.targetDescriptor.isSoftDelete();
|
||||
this.softDeletePredicate = (softDelete) ? property.targetDescriptor.getSoftDeletePredicate("") : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,6 +34,10 @@ class AssocOneHelpRefExported extends AssocOneHelp {
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
|
||||
String relativePrefix = ctx.getRelativePrefix(property.getName());
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
if (softDelete && !ctx.isIncludeSoftDelete()) {
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx, softDeletePredicate);
|
||||
} else {
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ public interface DbSqlContext {
|
||||
*/
|
||||
void addJoin(String type, String table, TableJoinColumn[] cols, String a1, String a2, String inheritance);
|
||||
|
||||
void pushSecondaryTableAlias(String alias);
|
||||
|
||||
/**
|
||||
* Push the current table alias onto the stack.
|
||||
*/
|
||||
@@ -91,11 +89,6 @@ public interface DbSqlContext {
|
||||
*/
|
||||
String getContent();
|
||||
|
||||
/**
|
||||
* Return the current join node.
|
||||
*/
|
||||
String peekJoin();
|
||||
|
||||
/**
|
||||
* Push a join node onto the stack.
|
||||
*/
|
||||
@@ -125,6 +118,11 @@ public interface DbSqlContext {
|
||||
*/
|
||||
void appendHistorySysPeriod();
|
||||
|
||||
/**
|
||||
* Return true if the query includes soft deleted rows.
|
||||
*/
|
||||
boolean isIncludeSoftDelete();
|
||||
|
||||
/**
|
||||
* Return true if the query is a 'asDraft' query.
|
||||
*/
|
||||
@@ -139,4 +137,5 @@ public interface DbSqlContext {
|
||||
* Append 'for update' lock hints on FROM clause (sql server only).
|
||||
*/
|
||||
void appendFromForUpdate();
|
||||
|
||||
}
|
||||
|
||||
@@ -126,6 +126,16 @@ public final class TableJoin {
|
||||
return type;
|
||||
}
|
||||
|
||||
public SqlJoinType addJoin(SqlJoinType joinType, String prefix, DbSqlContext ctx, String predicate) {
|
||||
String[] names = SplitName.split(prefix);
|
||||
String a1 = ctx.getTableAlias(names[0]);
|
||||
String a2 = ctx.getTableAlias(prefix);
|
||||
|
||||
SqlJoinType returnJoinType = addJoin(joinType, a1, a2, ctx);
|
||||
ctx.append("and ").append(a2).append(predicate);
|
||||
return returnJoinType;
|
||||
}
|
||||
|
||||
public SqlJoinType addJoin(SqlJoinType joinType, String prefix, DbSqlContext ctx) {
|
||||
|
||||
String[] names = SplitName.split(prefix);
|
||||
|
||||
@@ -70,6 +70,11 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
this.fromForUpdate = fromForUpdate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludeSoftDelete() {
|
||||
return alias.isIncludeSoftDelete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendFromForUpdate() {
|
||||
if (fromForUpdate != null) {
|
||||
@@ -99,11 +104,6 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
return encryptedProps.toArray(new BeanProperty[encryptedProps.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String peekJoin() {
|
||||
return joinStack.peek();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popJoin() {
|
||||
joinStack.pop();
|
||||
@@ -206,11 +206,6 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
return alias.getTableAliasManyWhere(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushSecondaryTableAlias(String alias) {
|
||||
tableAliasStack.push(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePrefix(String propName) {
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -17,6 +18,8 @@ class SqlTreeAlias {
|
||||
|
||||
private static final Pattern TABLE_ALIAS_REPLACE = Pattern.compile("${}", Pattern.LITERAL);
|
||||
|
||||
private final SpiQuery.TemporalMode temporalMode;
|
||||
|
||||
private int counter;
|
||||
|
||||
private int manyWhereCounter;
|
||||
@@ -33,8 +36,9 @@ class SqlTreeAlias {
|
||||
|
||||
private final String rootTableAlias;
|
||||
|
||||
SqlTreeAlias(String rootTableAlias) {
|
||||
SqlTreeAlias(String rootTableAlias, SpiQuery.TemporalMode temporalMode) {
|
||||
this.rootTableAlias = rootTableAlias;
|
||||
this.temporalMode = temporalMode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,4 +215,8 @@ class SqlTreeAlias {
|
||||
boolean isIncludeJoins() {
|
||||
return !aliasMap.isEmpty() || !manyWhereAliasMap.isEmpty();
|
||||
}
|
||||
|
||||
boolean isIncludeSoftDelete() {
|
||||
return temporalMode == SpiQuery.TemporalMode.SOFT_DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ public final class SqlTreeBuilder {
|
||||
this.queryDetail = query.getDetail();
|
||||
|
||||
this.predicates = predicates;
|
||||
this.alias = new SqlTreeAlias(request.getBaseTableAlias());
|
||||
this.alias = new SqlTreeAlias(request.getBaseTableAlias(), temporalMode);
|
||||
this.distinctOnPlatform = builder.isPlatformDistinctOn();
|
||||
|
||||
String fromForUpdate = builder.fromForUpdate(query);
|
||||
|
||||
@@ -351,7 +351,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
if (type.equals(List.class)) {
|
||||
if (arrayTypeListFactory != null) {
|
||||
if (isEnumType(valueType)) {
|
||||
return arrayTypeListFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), EnumType.STRING));
|
||||
return arrayTypeListFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null));
|
||||
}
|
||||
return arrayTypeListFactory.typeFor(valueType);
|
||||
}
|
||||
@@ -360,7 +360,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
} else if (type.equals(Set.class)) {
|
||||
if (arrayTypeSetFactory != null) {
|
||||
if (isEnumType(valueType)) {
|
||||
return arrayTypeSetFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), EnumType.STRING));
|
||||
return arrayTypeSetFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null));
|
||||
}
|
||||
return arrayTypeSetFactory.typeFor(valueType);
|
||||
}
|
||||
|
||||
@@ -13,16 +13,16 @@ if not exists (select name from sys.types where name = 'ebean_uniqueidentifier_
|
||||
if not exists (select name from sys.types where name = 'ebean_nvarchar_tvp') create type ebean_nvarchar_tvp as table (c1 nvarchar(max));
|
||||
|
||||
delimiter $$
|
||||
-----------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_indices TABLE, COLUMN
|
||||
-- deletes all indices referring to TABLE.COLUMN
|
||||
-----------------------------------------------------------
|
||||
--
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_indices @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
declare @indexName nvarchar(255)
|
||||
BEGIN
|
||||
DECLARE index_cursor CURSOR FOR SELECT i.name from sys.indexes i
|
||||
DECLARE index_cursor CURSOR FOR SELECT i.name from sys.indexes i
|
||||
join sys.index_columns ic on ic.object_id = i.object_id and ic.index_id = i.index_id
|
||||
join sys.columns c on c.object_id = ic.object_id and c.column_id = ic.column_id
|
||||
where i.object_id = OBJECT_ID(@tableName) AND c.name = @columnName;
|
||||
@@ -41,10 +41,10 @@ END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
--------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_default_constraint TABLE, COLUMN
|
||||
-- deletes the default constraint, which has a random name
|
||||
--------------------------------------------------------------------
|
||||
--
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_default_constraint @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @tmp nvarchar(1000)
|
||||
@@ -58,16 +58,16 @@ END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
--------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_constraints TABLE, COLUMN
|
||||
-- deletes constraints and foreign keys refering to TABLE.COLUMN
|
||||
--------------------------------------------------------------------
|
||||
--
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_constraints @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
declare @constraintName nvarchar(255)
|
||||
BEGIN
|
||||
DECLARE name_cursor CURSOR FOR
|
||||
DECLARE name_cursor CURSOR FOR
|
||||
SELECT cc.name from sys.check_constraints cc
|
||||
join sys.columns c on c.object_id = cc.parent_object_id and c.column_id = cc.parent_column_id
|
||||
where parent_object_id = OBJECT_ID(@tableName) AND c.name = @columnName
|
||||
@@ -92,10 +92,10 @@ END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
-------------------------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN
|
||||
-- deletes the column annd ensures that all indices and constraints are dropped first
|
||||
-------------------------------------------------------------------------------------
|
||||
--
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_column @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
@@ -114,21 +114,21 @@ $$
|
||||
DROP PROCEDURE IF EXISTS usp_ebean_drop_foreign_keys;
|
||||
|
||||
delimiter $$
|
||||
------------------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_foreign_keys TABLE, COLUMN
|
||||
-- deletes all constraints and foreign keys referring to TABLE.COLUMN
|
||||
------------------------------------------------------------------------------
|
||||
--
|
||||
CREATE PROCEDURE usp_ebean_drop_foreign_keys(IN p_table_name VARCHAR(255), IN p_column_name VARCHAR(255))
|
||||
BEGIN
|
||||
DECLARE done INT DEFAULT FALSE;
|
||||
DECLARE c_fk_name CHAR(255);
|
||||
DECLARE curs CURSOR FOR SELECT CONSTRAINT_NAME from information_schema.KEY_COLUMN_USAGE
|
||||
DECLARE curs CURSOR FOR SELECT CONSTRAINT_NAME from information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = DATABASE() and TABLE_NAME = p_table_name and COLUMN_NAME = p_column_name
|
||||
AND REFERENCED_TABLE_NAME IS NOT NULL;
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
|
||||
|
||||
OPEN curs;
|
||||
|
||||
|
||||
read_loop: LOOP
|
||||
FETCH curs INTO c_fk_name;
|
||||
IF done THEN
|
||||
@@ -138,7 +138,7 @@ BEGIN
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
END LOOP;
|
||||
|
||||
|
||||
CLOSE curs;
|
||||
END
|
||||
$$
|
||||
@@ -146,10 +146,10 @@ $$
|
||||
DROP PROCEDURE IF EXISTS usp_ebean_drop_column;
|
||||
|
||||
delimiter $$
|
||||
-------------------------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN
|
||||
-- deletes the column and ensures that all indices and constraints are dropped first
|
||||
-------------------------------------------------------------------------------------
|
||||
--
|
||||
CREATE PROCEDURE usp_ebean_drop_column(IN p_table_name VARCHAR(255), IN p_column_name VARCHAR(255))
|
||||
BEGIN
|
||||
CALL usp_ebean_drop_foreign_keys(p_table_name, p_column_name);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package io.ebeaninternal.dbmigration.model;
|
||||
|
||||
|
||||
import io.ebeaninternal.dbmigration.migration.DropHistoryTable;
|
||||
import io.ebeaninternal.dbmigration.migration.DropIndex;
|
||||
import io.ebeaninternal.dbmigration.migration.DropTable;
|
||||
import io.ebeaninternal.dbmigration.migration.Migration;
|
||||
import io.ebeaninternal.dbmigration.migrationreader.MigrationXmlReader;
|
||||
import org.junit.Test;
|
||||
@@ -79,6 +82,31 @@ public class ModelContainerTest {
|
||||
assertThat(container.getPendingDrops()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_dropTable_when_notInModel_then_ok() {
|
||||
|
||||
ModelContainer container = new ModelContainer();
|
||||
container.apply(mig("5.0__dropTable.model.xml"), ver("5.0"));
|
||||
assertThat(container.getTables()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_drop_when_notInModel_then_ok() {
|
||||
|
||||
ModelContainer container = new ModelContainer();
|
||||
DropTable dropTable = new DropTable();
|
||||
dropTable.setName("DoesNotExist");
|
||||
container.applyChange(dropTable);
|
||||
|
||||
DropIndex dropIndex = new DropIndex();
|
||||
dropIndex.setIndexName("DoesNotExist");
|
||||
container.applyChange(dropIndex);
|
||||
|
||||
DropHistoryTable dropHistoryTable = new DropHistoryTable();
|
||||
dropHistoryTable.setBaseTable("DoesNotExist");
|
||||
container.applyChange(dropHistoryTable);
|
||||
}
|
||||
|
||||
private ModelContainer container_2_1() {
|
||||
ModelContainer container = new ModelContainer();
|
||||
container.apply(mig("2.0.model.xml"), ver("2.0"));
|
||||
|
||||
@@ -72,7 +72,7 @@ public class TestQueryCacheTableDependency extends BaseTestCase {
|
||||
.findCount();
|
||||
assertThat(custs).isEqualTo(1);
|
||||
|
||||
Ebean.createSqlUpdate("update O_ADDRESS set line_2=? where line_2=?")
|
||||
Ebean.createSqlUpdate("update o_address set line_2=? where line_2=?")
|
||||
.setNextParameter("St Lucky3")
|
||||
.setNextParameter("St Lucky2")
|
||||
.execute();
|
||||
|
||||
@@ -18,6 +18,8 @@ public class EArrayBean {
|
||||
ONE, TWO, THREE
|
||||
}
|
||||
|
||||
IntEnum foo;
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
@@ -50,6 +52,14 @@ public class EArrayBean {
|
||||
@Version
|
||||
Long version;
|
||||
|
||||
public IntEnum getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(final IntEnum foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ import java.util.Objects;
|
||||
@Embeddable
|
||||
public class CkeUserKey {
|
||||
|
||||
@Basic(optional = false)
|
||||
@Column(name = "cod_cpny")
|
||||
private int codCompany;
|
||||
|
||||
@Basic(optional = false)
|
||||
@Column(name = "username")
|
||||
private String username;
|
||||
|
||||
@Basic(optional = false)
|
||||
@Column(name = "cod_cpny")
|
||||
private int codCompany;
|
||||
|
||||
public CkeUserKey(int codCompany, String username) {
|
||||
this.codCompany = codCompany;
|
||||
this.username = username;
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.tests.model.onetoone;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
@@ -13,7 +14,7 @@ public class OtoBMaster {
|
||||
|
||||
String name;
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL, mappedBy = "master")
|
||||
@OneToOne(cascade = CascadeType.ALL, mappedBy = "master", fetch = FetchType.LAZY)
|
||||
OtoBChild child;
|
||||
|
||||
public Long getId() {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.tests.model.onetoone;
|
||||
|
||||
import io.ebean.Finder;
|
||||
import io.ebean.annotation.SoftDelete;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class OtoSdChild {
|
||||
|
||||
public static Finder<Long, OtoSdChild> find = new Finder<>(OtoSdChild.class);
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String child;
|
||||
|
||||
@SoftDelete
|
||||
boolean deleted;
|
||||
|
||||
@OneToOne
|
||||
OtoSdMaster master;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public OtoSdChild(String child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getChild() {
|
||||
return child;
|
||||
}
|
||||
|
||||
public void setChild(String child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public OtoSdMaster getMaster() {
|
||||
return master;
|
||||
}
|
||||
|
||||
public void setMaster(OtoSdMaster master) {
|
||||
this.master = master;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.tests.model.onetoone;
|
||||
|
||||
import io.ebean.Finder;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class OtoSdMaster {
|
||||
|
||||
public static Finder<Long, OtoSdMaster> find = new Finder<>(OtoSdMaster.class);
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL, mappedBy = "master")//, fetch = FetchType.LAZY)
|
||||
OtoSdChild child;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public OtoSdMaster(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public OtoSdChild getChild() {
|
||||
return child;
|
||||
}
|
||||
|
||||
public void setChild(OtoSdChild child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,12 +3,53 @@ package org.tests.model.onetoone;
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Query;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestOneToOneImportedPkNative extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void findWithLazyOneToOne() {
|
||||
|
||||
OtoBChild child = new OtoBChild();
|
||||
child.setChild("c1");
|
||||
|
||||
OtoBMaster master = new OtoBMaster();
|
||||
master.setName("m2");
|
||||
master.setChild(child);
|
||||
|
||||
Ebean.save(master);
|
||||
|
||||
Query<OtoBMaster> query = Ebean.find(OtoBMaster.class)
|
||||
//.select("name")
|
||||
.where().idEq(master.getId())
|
||||
.query();
|
||||
|
||||
OtoBMaster one = query.findOne();
|
||||
|
||||
String sql = sqlOf(query);
|
||||
assertThat(sql).contains("select t0.id, t0.name from oto_bmaster t0 where t0.id ");
|
||||
assertThat(sql).doesNotContain("left join oto_bchild");
|
||||
|
||||
assertThat(one).isNotNull();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
OtoBChild child1 = one.getChild();
|
||||
assertThat(child1).isNotNull();
|
||||
assertThat(child1.getChild()).isEqualTo("c1");
|
||||
|
||||
List<String> lazyLoadSql = LoggedSqlCollector.stop();
|
||||
assertThat(lazyLoadSql).hasSize(2);
|
||||
assertThat(lazyLoadSql.get(0)).contains("select t0.id, t0.name, t1.master_id from oto_bmaster t0 left join oto_bchild t1");
|
||||
assertThat(lazyLoadSql.get(1)).contains("select t0.master_id, t0.child, t0.master_id from oto_bchild t0 where t0.master_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void native_with_o2oAndImportedPrimaryKey() {
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.tests.model.onetoone;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestOneToOneSoftDeleteChild extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void deleteChild() {
|
||||
|
||||
|
||||
OtoSdChild child = new OtoSdChild("c1");
|
||||
OtoSdMaster master = new OtoSdMaster("m1");
|
||||
master.setChild(child);
|
||||
|
||||
Ebean.save(master);
|
||||
|
||||
|
||||
verifyBeforeDelete(master, child);
|
||||
|
||||
Ebean.delete(child);
|
||||
|
||||
verifyAfterDelete(master, child);
|
||||
}
|
||||
|
||||
private void verifyBeforeDelete(OtoSdMaster parent, OtoSdChild child) {
|
||||
assertThat(OtoSdMaster.find.byId(parent.getId()).getChild().getId())
|
||||
.isEqualTo(child.getId());
|
||||
|
||||
assertThat(
|
||||
OtoSdChild.find.byId(child.getId()).getMaster().getId())
|
||||
.isEqualTo(parent.getId());
|
||||
}
|
||||
|
||||
private void verifyAfterDelete(OtoSdMaster parent, OtoSdChild child) {
|
||||
// After delete, finding child by id should return null
|
||||
assertThat(OtoSdChild.find.byId(child.getId()))
|
||||
.isNull();
|
||||
|
||||
// After delete, getting linked child from parent should return null
|
||||
assertThat(OtoSdMaster.find.byId(parent.getId()).getChild())
|
||||
.isNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.tests.model.orphanremoval;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class OrpDetail {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
|
||||
String detail;
|
||||
|
||||
@ManyToOne
|
||||
OrpMaster master;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public OrpDetail(String id, String detail) {
|
||||
this.id = id;
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public OrpMaster getMaster() {
|
||||
return master;
|
||||
}
|
||||
|
||||
public void setMaster(OrpMaster master) {
|
||||
this.master = master;
|
||||
}
|
||||
|
||||
public String getDetail() {
|
||||
return detail;
|
||||
}
|
||||
|
||||
public void setDetail(String detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.tests.model.orphanremoval;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Version;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class OrpMaster {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
|
||||
String name;
|
||||
|
||||
@OneToMany(orphanRemoval = true, cascade = CascadeType.ALL)
|
||||
List<OrpDetail> details;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public OrpMaster(String id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<OrpDetail> getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
public void setDetails(List<OrpDetail> details) {
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.tests.model.orphanremoval;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestOrphanRemoveO2M extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void clear_expect_deletes() {
|
||||
|
||||
OrpMaster master = new OrpMaster("m","master");
|
||||
master.getDetails().add(new OrpDetail("d1", "d1"));
|
||||
master.getDetails().add(new OrpDetail("d2", "d2"));
|
||||
|
||||
Ebean.save(master);
|
||||
|
||||
master.getDetails().clear();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.save(master);
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
|
||||
assertThat(Ebean.find(OrpDetail.class, "d1")).isNull();
|
||||
assertThat(Ebean.find(OrpDetail.class, "d2")).isNull();
|
||||
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("delete from orp_detail where id=?");
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,21 @@
|
||||
DROP PROCEDURE IF EXISTS usp_ebean_drop_foreign_keys;
|
||||
|
||||
delimiter $$
|
||||
------------------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_foreign_keys TABLE, COLUMN
|
||||
-- deletes all constraints and foreign keys referring to TABLE.COLUMN
|
||||
------------------------------------------------------------------------------
|
||||
--
|
||||
CREATE PROCEDURE usp_ebean_drop_foreign_keys(IN p_table_name VARCHAR(255), IN p_column_name VARCHAR(255))
|
||||
BEGIN
|
||||
DECLARE done INT DEFAULT FALSE;
|
||||
DECLARE c_fk_name CHAR(255);
|
||||
DECLARE curs CURSOR FOR SELECT CONSTRAINT_NAME from information_schema.KEY_COLUMN_USAGE
|
||||
DECLARE curs CURSOR FOR SELECT CONSTRAINT_NAME from information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = DATABASE() and TABLE_NAME = p_table_name and COLUMN_NAME = p_column_name
|
||||
AND REFERENCED_TABLE_NAME IS NOT NULL;
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
|
||||
|
||||
OPEN curs;
|
||||
|
||||
|
||||
read_loop: LOOP
|
||||
FETCH curs INTO c_fk_name;
|
||||
IF done THEN
|
||||
@@ -26,7 +26,7 @@ BEGIN
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
END LOOP;
|
||||
|
||||
|
||||
CLOSE curs;
|
||||
END
|
||||
$$
|
||||
@@ -34,10 +34,10 @@ $$
|
||||
DROP PROCEDURE IF EXISTS usp_ebean_drop_column;
|
||||
|
||||
delimiter $$
|
||||
-------------------------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN
|
||||
-- deletes the column and ensures that all indices and constraints are dropped first
|
||||
-------------------------------------------------------------------------------------
|
||||
--
|
||||
CREATE PROCEDURE usp_ebean_drop_column(IN p_table_name VARCHAR(255), IN p_column_name VARCHAR(255))
|
||||
BEGIN
|
||||
CALL usp_ebean_drop_foreign_keys(p_table_name, p_column_name);
|
||||
|
||||
@@ -10,16 +10,16 @@ if not exists (select name from sys.types where name = 'ebean_uniqueidentifier_
|
||||
if not exists (select name from sys.types where name = 'ebean_nvarchar_tvp') create type ebean_nvarchar_tvp as table (c1 nvarchar(max));
|
||||
|
||||
delimiter $$
|
||||
-----------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_indices TABLE, COLUMN
|
||||
-- deletes all indices referring to TABLE.COLUMN
|
||||
-----------------------------------------------------------
|
||||
--
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_indices @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
declare @indexName nvarchar(255)
|
||||
BEGIN
|
||||
DECLARE index_cursor CURSOR FOR SELECT i.name from sys.indexes i
|
||||
DECLARE index_cursor CURSOR FOR SELECT i.name from sys.indexes i
|
||||
join sys.index_columns ic on ic.object_id = i.object_id and ic.index_id = i.index_id
|
||||
join sys.columns c on c.object_id = ic.object_id and c.column_id = ic.column_id
|
||||
where i.object_id = OBJECT_ID(@tableName) AND c.name = @columnName;
|
||||
@@ -38,10 +38,10 @@ END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
--------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_default_constraint TABLE, COLUMN
|
||||
-- deletes the default constraint, which has a random name
|
||||
--------------------------------------------------------------------
|
||||
--
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_default_constraint @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @tmp nvarchar(1000)
|
||||
@@ -55,16 +55,16 @@ END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
--------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_constraints TABLE, COLUMN
|
||||
-- deletes constraints and foreign keys refering to TABLE.COLUMN
|
||||
--------------------------------------------------------------------
|
||||
--
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_constraints @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
declare @constraintName nvarchar(255)
|
||||
BEGIN
|
||||
DECLARE name_cursor CURSOR FOR
|
||||
DECLARE name_cursor CURSOR FOR
|
||||
SELECT cc.name from sys.check_constraints cc
|
||||
join sys.columns c on c.object_id = cc.parent_object_id and c.column_id = cc.parent_column_id
|
||||
where parent_object_id = OBJECT_ID(@tableName) AND c.name = @columnName
|
||||
@@ -89,10 +89,10 @@ END
|
||||
$$
|
||||
|
||||
delimiter $$
|
||||
-------------------------------------------------------------------------------------
|
||||
--
|
||||
-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN
|
||||
-- deletes the column annd ensures that all indices and constraints are dropped first
|
||||
-------------------------------------------------------------------------------------
|
||||
--
|
||||
CREATE OR ALTER PROCEDURE usp_ebean_drop_column @tableName nvarchar(255), @columnName nvarchar(255)
|
||||
AS SET NOCOUNT ON
|
||||
declare @sql nvarchar(1000)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
<dropTable name="some_table"/>
|
||||
</changeSet>
|
||||
</migration>
|
||||
Reference in New Issue
Block a user