Skip to content

Commit cc48dce

Browse files
authored
#3572 DDL support for non-nullable JoinColumn column (#3575)
1 parent 0a5c3ce commit cc48dce

File tree

9 files changed

+154
-21
lines changed

9 files changed

+154
-21
lines changed

ebean-core/src/main/java/io/ebeaninternal/server/deploy/TableJoinColumn.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public final class TableJoinColumn {
2020
private final String foreignSqlFormula;
2121
private final boolean insertable;
2222
private final boolean updateable;
23+
private final boolean nullable;
2324
/**
2425
* Hash for including in a query plan
2526
*/
@@ -34,7 +35,8 @@ public TableJoinColumn(DeployTableJoinColumn deploy) {
3435
this.localSqlFormula = InternString.intern(deploy.getLocalSqlFormula());
3536
this.foreignSqlFormula = InternString.intern(deploy.getForeignSqlFormula());
3637
this.insertable = deploy.isInsertable();
37-
this.updateable = deploy.isUpdateable();
38+
this.updateable = deploy.isUpdatable();
39+
this.nullable = deploy.isNullable();
3840
this.queryHash = hash();
3941
}
4042

@@ -45,6 +47,7 @@ private TableJoinColumn(TableJoinColumn source, String overrideColumn) {
4547
this.foreignSqlFormula = null;
4648
this.insertable = source.isInsertable();
4749
this.updateable = source.isUpdateable();
50+
this.nullable = source.isNullable();
4851
this.queryHash = hash();
4952
}
5053

@@ -115,6 +118,13 @@ boolean isUpdateable() {
115118
return updateable;
116119
}
117120

121+
/**
122+
* Return if this column is nullable.
123+
*/
124+
public boolean isNullable() {
125+
return nullable;
126+
}
127+
118128
public String getLocalSqlFormula() {
119129
return localSqlFormula;
120130
}

ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployTableJoin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public void addJoinColumn(DeployUtil deploy, boolean order, JoinColumn jc, BeanT
8181
// only add the join column details when name or referencedColumnName is specified
8282
String ref = deploy.convertQuotes(jc.referencedColumnName());
8383
String nam = deploy.convertQuotes(jc.name());
84-
addJoinColumn(new DeployTableJoinColumn(order, ref, nam, jc.insertable(), jc.updatable(), beanTable));
84+
addJoinColumn(new DeployTableJoinColumn(order, ref, nam, jc.insertable(), jc.updatable(), jc.nullable(), beanTable));
8585
}
8686
}
8787

ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployTableJoinColumn.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public final class DeployTableJoinColumn {
2525
*/
2626
private String foreignSqlFormula;
2727
private boolean insertable;
28-
private boolean updateable;
28+
private boolean updatable;
29+
private boolean nullable;
2930

3031
/**
3132
* Construct when automatically determining the join.
@@ -34,21 +35,24 @@ public final class DeployTableJoinColumn {
3435
* </p>
3536
*/
3637
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn) {
37-
this(localDbColumn, foreignDbColumn, true, true);
38+
this(localDbColumn, foreignDbColumn, true, true, true);
3839
}
3940

4041
/**
4142
* Construct with explicit insertable and updateable flags.
4243
*/
43-
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
44+
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn,
45+
boolean insertable, boolean updatable, boolean nullable) {
4446
this.localDbColumn = nullEmptyString(localDbColumn);
4547
this.foreignDbColumn = nullEmptyString(foreignDbColumn);
4648
this.insertable = insertable;
47-
this.updateable = updateable;
49+
this.updatable = updatable;
50+
this.nullable = nullable;
4851
}
4952

50-
public DeployTableJoinColumn(boolean order, String ref, String name, boolean insertable, boolean updateable, BeanTable beanTable) {
51-
this(ref, name, insertable, updateable);
53+
public DeployTableJoinColumn(boolean order, String ref, String name,
54+
boolean insertable, boolean updatable, boolean nullable, BeanTable beanTable) {
55+
this(ref, name, insertable, updatable, nullable);
5256
setReferencedColumn(beanTable);
5357
if (!order) {
5458
reverse();
@@ -60,7 +64,7 @@ void setLocalSqlFormula(String localSqlFormula) {
6064
this.localSqlFormula = localSqlFormula;
6165
this.localDbColumn = null;
6266
this.insertable = false;
63-
this.updateable = false;
67+
this.updatable = false;
6468
}
6569
}
6670

@@ -73,7 +77,7 @@ public void setForeignSqlFormula(String foreignSqlFormula) {
7377
this.foreignSqlFormula = foreignSqlFormula;
7478
this.foreignDbColumn = null;
7579
this.insertable = false;
76-
this.updateable = false;
80+
this.updatable = false;
7781
}
7882
}
7983

@@ -121,12 +125,12 @@ public DeployTableJoinColumn copy(boolean reverse) {
121125
// but will leave it like this for now
122126
DeployTableJoinColumn ret;
123127
if (reverse) {
124-
ret = new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updateable);
128+
ret = new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updatable, nullable);
125129
ret.setLocalSqlFormula(foreignSqlFormula);
126130
ret.setForeignSqlFormula(localSqlFormula);
127131

128132
} else {
129-
ret = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
133+
ret = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updatable, nullable);
130134
ret.setLocalSqlFormula(localSqlFormula);
131135
ret.setForeignSqlFormula(foreignSqlFormula);
132136
}
@@ -148,8 +152,8 @@ public boolean isInsertable() {
148152
/**
149153
* Return true if this column should be updateable.
150154
*/
151-
public boolean isUpdateable() {
152-
return updateable;
155+
public boolean isUpdatable() {
156+
return updatable;
153157
}
154158

155159
/**
@@ -173,4 +177,7 @@ void setLocalDbColumn(String localDbColumn) {
173177
this.localDbColumn = localDbColumn;
174178
}
175179

180+
public boolean isNullable() {
181+
return nullable;
182+
}
176183
}

ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationAssocOnes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ private void readPrimaryKeyJoin(PrimaryKeyJoinColumn primaryKeyJoin, DeployBeanP
223223
BeanTable baseBeanTable = factory.beanTable(info.getDescriptor().getBeanType());
224224
String localPrimaryKey = baseBeanTable.getIdColumn();
225225
String foreignColumn = getBeanTable(prop).getIdColumn();
226-
prop.getTableJoin().addJoinColumn(new DeployTableJoinColumn(localPrimaryKey, foreignColumn, false, false));
226+
prop.getTableJoin().addJoinColumn(new DeployTableJoinColumn(localPrimaryKey, foreignColumn, false, false, prop.isNullable()));
227227
}
228228

229229
private void readEmbedded(DeployBeanPropertyAssocOne<?> prop, Embedded embedded) {

ebean-core/src/test/java/io/ebeaninternal/server/deploy/TableJoinColumnTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
public class TableJoinColumnTest {
99

1010
TableJoinColumn col(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
11-
DeployTableJoinColumn column = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
11+
DeployTableJoinColumn column = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable, true);
1212
return new TableJoinColumn(column);
1313
}
1414

ebean-core/src/test/java/io/ebeaninternal/server/deploy/TableJoinTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@
99

1010
public class TableJoinTest {
1111

12-
DeployTableJoinColumn col(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
13-
return new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
12+
DeployTableJoinColumn col(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable, boolean nullable) {
13+
return new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable, nullable);
1414
}
1515

1616
TableJoin table(String tableName, String col1, String col2) {
1717
DeployTableJoin deploy = new DeployTableJoin();
1818
deploy.setTable(tableName);
19-
deploy.addJoinColumn(col(col1, col2, true, true));
19+
deploy.addJoinColumn(col(col1, col2, true, true, true));
2020
return new TableJoin(deploy);
2121
}
2222

2323
TableJoin table(String tableName, String col1, String col2, String col3, String col4) {
2424
DeployTableJoin deploy = new DeployTableJoin();
2525
deploy.setTable(tableName);
26-
deploy.addJoinColumn(col(col1, col2, true, true));
27-
deploy.addJoinColumn(col(col3, col4, true, true));
26+
deploy.addJoinColumn(col(col1, col2, true, true, true));
27+
deploy.addJoinColumn(col(col3, col4, true, true, true));
2828
return new TableJoin(deploy);
2929
}
3030

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.tests.compositekeys;
2+
3+
import io.ebean.DB;
4+
import io.ebean.xtest.BaseTestCase;
5+
import org.junit.jupiter.api.Test;
6+
import org.tests.compositekeys.db.PartitionKey;
7+
import org.tests.compositekeys.db.EmbeddedSelfRelation;
8+
9+
import static org.assertj.core.api.Assertions.assertThat;
10+
11+
class TestRecursiveEmbeddedId extends BaseTestCase {
12+
13+
@Test
14+
void insert() {
15+
PartitionKey partitionKey = new PartitionKey(78L, 1000L);
16+
EmbeddedSelfRelation bean0 = new EmbeddedSelfRelation(partitionKey);
17+
DB.save(bean0);
18+
19+
var found = DB.find(EmbeddedSelfRelation.class).where().eq("key", new PartitionKey(78L, 1000L)).findOne();
20+
assertThat(found).isNotNull();
21+
assertThat(found.key().orgId()).isEqualTo(78L);
22+
assertThat(found.key().code()).isEqualTo(1000L);
23+
assertThat(found.root().key()).isNotNull();
24+
assertThat(found.root().key().orgId()).isEqualTo(78L);
25+
assertThat(found.root().key().code()).isNull();
26+
27+
var bean1 = new EmbeddedSelfRelation(new PartitionKey(78L, 1001L));
28+
bean1.setRoot(bean0);
29+
DB.save(bean1);
30+
31+
var found2 = DB.find(EmbeddedSelfRelation.class).where().eq("key", new PartitionKey(78L, 1001L)).findOne();
32+
assertThat(found2).isNotNull();
33+
assertThat(found2.key().code()).isEqualTo(1001L);
34+
35+
assertThat(found2.root().key().orgId()).isEqualTo(78L);
36+
assertThat(found2.root().key().code()).isEqualTo(1000L);
37+
}
38+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.tests.compositekeys.db;
2+
3+
import jakarta.persistence.*;
4+
5+
@Entity
6+
@Table(name = "em_transactions")
7+
public class EmbeddedSelfRelation {
8+
9+
@EmbeddedId
10+
private final PartitionKey key;
11+
12+
@ManyToOne
13+
@JoinColumns({
14+
@JoinColumn(name = "org_id", referencedColumnName = "org_id", insertable = false, updatable = false),
15+
@JoinColumn(name = "root_code", referencedColumnName = "code"),
16+
})
17+
private EmbeddedSelfRelation root;
18+
19+
public EmbeddedSelfRelation(PartitionKey key) {
20+
this.key = key;
21+
}
22+
23+
public PartitionKey key() {
24+
return key;
25+
}
26+
27+
public EmbeddedSelfRelation root() {
28+
return root;
29+
}
30+
31+
public void setRoot(EmbeddedSelfRelation root) {
32+
this.root = root;
33+
}
34+
}
35+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.tests.compositekeys.db;
2+
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Embeddable;
5+
6+
import java.io.Serializable;
7+
import java.util.Objects;
8+
9+
@Embeddable
10+
public class PartitionKey implements Serializable {
11+
12+
@Column(name = "org_id")
13+
private final Long orgId;
14+
@Column(name = "code")
15+
private final Long code;
16+
17+
public PartitionKey(Long orgId, Long code) {
18+
this.orgId = orgId;
19+
this.code= code;
20+
}
21+
22+
public Long orgId() {
23+
return orgId;
24+
}
25+
26+
public Long code() {
27+
return code;
28+
}
29+
30+
@Override
31+
public boolean equals(Object o) {
32+
if (this == o) return true;
33+
if (o == null || getClass() != o.getClass()) return false;
34+
PartitionKey that = (PartitionKey) o;
35+
return Objects.equals(orgId, that.orgId) && Objects.equals(code, that.code);
36+
}
37+
38+
@Override
39+
public int hashCode() {
40+
return Objects.hash(orgId, code);
41+
}
42+
}
43+

0 commit comments

Comments
 (0)