mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#595 - Refactor - persistence context root type handling - AssocOne split simple and inherit
This commit is contained in:
@@ -11,10 +11,17 @@ import java.sql.SQLException;
|
||||
*/
|
||||
abstract class AssocOneHelp {
|
||||
|
||||
protected final BeanPropertyAssocOne property;
|
||||
|
||||
AssocOneHelp(BeanPropertyAssocOne property) {
|
||||
this.property = property;
|
||||
}
|
||||
/**
|
||||
* Effectively skip reading (the jdbc resultSet as already in the persistence context etc).
|
||||
*/
|
||||
abstract void loadIgnore(DbReadContext ctx);
|
||||
void loadIgnore(DbReadContext ctx) {
|
||||
property.targetIdBinder.loadIgnore(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and return the bean.
|
||||
@@ -24,7 +31,14 @@ abstract class AssocOneHelp {
|
||||
/**
|
||||
* Read setting values into the bean.
|
||||
*/
|
||||
abstract Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException;
|
||||
Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
|
||||
Object val = read(ctx);
|
||||
if (bean != null) {
|
||||
property.setValue(bean, val);
|
||||
ctx.propagateState(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append to the select clause.
|
||||
@@ -34,6 +48,8 @@ abstract class AssocOneHelp {
|
||||
/**
|
||||
* Append to the from clause.
|
||||
*/
|
||||
abstract void appendFrom(DbSqlContext ctx, SqlJoinType joinType);
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
// nothing required here
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -10,15 +9,13 @@ import java.sql.SQLException;
|
||||
*/
|
||||
final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
|
||||
private BeanPropertyAssocOne beanPropertyAssocOne;
|
||||
|
||||
public AssocOneHelpEmbedded(BeanPropertyAssocOne beanPropertyAssocOne) {
|
||||
this.beanPropertyAssocOne = beanPropertyAssocOne;
|
||||
public AssocOneHelpEmbedded(BeanPropertyAssocOne property) {
|
||||
super(property);
|
||||
}
|
||||
|
||||
void loadIgnore(DbReadContext ctx) {
|
||||
for (int i = 0; i < beanPropertyAssocOne.embeddedProps.length; i++) {
|
||||
beanPropertyAssocOne.embeddedProps[i].loadIgnore(ctx);
|
||||
for (int i = 0; i < property.embeddedProps.length; i++) {
|
||||
property.embeddedProps[i].loadIgnore(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +24,9 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
Object dbVal = read(ctx);
|
||||
if (bean != null) {
|
||||
// set back to the parent bean
|
||||
beanPropertyAssocOne.setValue(bean, dbVal);
|
||||
property.setValue(bean, dbVal);
|
||||
ctx.propagateState(dbVal);
|
||||
return dbVal;
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -39,11 +35,11 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
@Override
|
||||
Object read(DbReadContext ctx) throws SQLException {
|
||||
|
||||
EntityBean embeddedBean = beanPropertyAssocOne.targetDescriptor.createEntityBean();
|
||||
EntityBean embeddedBean = property.targetDescriptor.createEntityBean();
|
||||
|
||||
boolean notNull = false;
|
||||
for (int i = 0; i < beanPropertyAssocOne.embeddedProps.length; i++) {
|
||||
Object value = beanPropertyAssocOne.embeddedProps[i].readSet(ctx, embeddedBean);
|
||||
for (int i = 0; i < property.embeddedProps.length; i++) {
|
||||
Object value = property.embeddedProps[i].readSet(ctx, embeddedBean);
|
||||
if (value != null) {
|
||||
notNull = true;
|
||||
}
|
||||
@@ -56,14 +52,10 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
for (int i = 0; i < beanPropertyAssocOne.embeddedProps.length; i++) {
|
||||
beanPropertyAssocOne.embeddedProps[i].appendSelect(ctx, subQuery);
|
||||
for (int i = 0; i < property.embeddedProps.length; i++) {
|
||||
property.embeddedProps[i].appendSelect(ctx, subQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebean.bean.PersistenceContextUtil;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Helper for BeanPropertyAssocOne imported reference but with inheritance.
|
||||
*/
|
||||
class AssocOneHelpRefInherit extends AssocOneHelp {
|
||||
|
||||
private final InheritInfo inherit;
|
||||
|
||||
AssocOneHelpRefInherit(BeanPropertyAssocOne property) {
|
||||
super(property);
|
||||
this.inherit = property.targetInheritInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
void loadIgnore(DbReadContext ctx) {
|
||||
property.targetIdBinder.loadIgnore(ctx);
|
||||
ctx.getDataReader().incrementPos(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and set a Reference bean.
|
||||
*/
|
||||
@Override
|
||||
Object read(DbReadContext ctx) throws SQLException {
|
||||
|
||||
// read discriminator to determine the type
|
||||
InheritInfo rowInheritInfo = inherit.readType(ctx);
|
||||
if (rowInheritInfo == null) {
|
||||
return null;
|
||||
}
|
||||
BeanDescriptor<?> desc = rowInheritInfo.getBeanDescriptor();
|
||||
|
||||
// read the foreign key column(s)
|
||||
Object id = property.targetIdBinder.read(ctx);
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// check transaction context to see if it already exists
|
||||
Class<?> rowType = desc.rootBeanType;
|
||||
Object existing = ctx.getPersistenceContext().get(rowType, id);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
// for inheritance hierarchy create the correct type for this row...
|
||||
Object ref = desc.createReference(ctx.isReadOnly(), id);
|
||||
|
||||
Class<?> rootType = PersistenceContextUtil.root(ref.getClass());
|
||||
ctx.getPersistenceContext().put(rootType, id, ref);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept();
|
||||
ctx.register(property.name, ebi);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
@Override
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
|
||||
// add join to support the discriminator column
|
||||
String relativePrefix = ctx.getRelativePrefix(property.name);
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append columns for foreign key columns.
|
||||
*/
|
||||
@Override
|
||||
void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
|
||||
if (!subQuery) {
|
||||
// add discriminator column
|
||||
String relativePrefix = ctx.getRelativePrefix(property.getName());
|
||||
String tableAlias = ctx.getTableAlias(relativePrefix);
|
||||
ctx.appendColumn(tableAlias, property.targetInheritInfo.getDiscriminatorColumn());
|
||||
}
|
||||
property.importedId.sqlAppend(ctx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Helper for BeanPropertyAssocOne imported reference - this is the common case.
|
||||
*/
|
||||
class AssocOneHelpRefSimple extends AssocOneHelp {
|
||||
|
||||
private final BeanDescriptor target;
|
||||
|
||||
AssocOneHelpRefSimple(BeanPropertyAssocOne property) {
|
||||
super(property);
|
||||
this.target = property.targetDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and set a Reference bean.
|
||||
*/
|
||||
@Override
|
||||
Object read(DbReadContext ctx) throws SQLException {
|
||||
|
||||
// read the foreign key column(s)
|
||||
Object id = property.targetIdBinder.read(ctx);
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> rowType = property.targetType;
|
||||
|
||||
// check transaction context to see if it already exists
|
||||
Object existing = ctx.getPersistenceContext().get(rowType, id);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
Object ref = target.createReference(ctx.isReadOnly(), id);
|
||||
target.contextPut(ctx.getPersistenceContext(), id, ref);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept();
|
||||
ctx.register(property.name, ebi);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append columns for foreign key columns.
|
||||
*/
|
||||
@Override
|
||||
void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
property.importedId.sqlAppend(ctx);
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebean.bean.PersistenceContextUtil;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Helper for BeanPropertyAssocOne imported reference - this is the common case.
|
||||
*/
|
||||
final class AssocOneHelpReference extends AssocOneHelp {
|
||||
|
||||
private BeanPropertyAssocOne beanPropertyAssocOne;
|
||||
|
||||
AssocOneHelpReference(BeanPropertyAssocOne beanPropertyAssocOne) {
|
||||
this.beanPropertyAssocOne = beanPropertyAssocOne;
|
||||
}
|
||||
|
||||
@Override
|
||||
void loadIgnore(DbReadContext ctx) {
|
||||
beanPropertyAssocOne.targetIdBinder.loadIgnore(ctx);
|
||||
if (beanPropertyAssocOne.targetInheritInfo != null) {
|
||||
ctx.getDataReader().incrementPos(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
|
||||
Object val = read(ctx);
|
||||
if (bean != null) {
|
||||
beanPropertyAssocOne.setValue(bean, val);
|
||||
ctx.propagateState(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and set a Reference bean.
|
||||
*/
|
||||
@Override
|
||||
Object read(DbReadContext ctx) throws SQLException {
|
||||
|
||||
BeanDescriptor<?> rowDescriptor = null;
|
||||
Class<?> rowType = beanPropertyAssocOne.targetType;
|
||||
if (beanPropertyAssocOne.targetInheritInfo != null) {
|
||||
// read discriminator to determine the type
|
||||
InheritInfo rowInheritInfo = beanPropertyAssocOne.targetInheritInfo.readType(ctx);
|
||||
if (rowInheritInfo != null) {
|
||||
rowType = rowInheritInfo.getType();
|
||||
rowDescriptor = rowInheritInfo.getBeanDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
// read the foreign key column(s)
|
||||
Object id = beanPropertyAssocOne.targetIdBinder.read(ctx);
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// check transaction context to see if it already exists
|
||||
Object existing = ctx.getPersistenceContext().get(rowType, id);
|
||||
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
Boolean readOnly = ctx.isReadOnly();
|
||||
Object ref;
|
||||
if (beanPropertyAssocOne.targetInheritInfo != null) {
|
||||
// for inheritance hierarchy create the correct type for this row...
|
||||
ref = rowDescriptor.createReference(readOnly, id);
|
||||
} else {
|
||||
ref = beanPropertyAssocOne.targetDescriptor.createReference(readOnly, id);
|
||||
}
|
||||
|
||||
Class<?> rootType = PersistenceContextUtil.root(ref.getClass());
|
||||
Object existingBean = ctx.getPersistenceContext().putIfAbsent(rootType, id, ref);
|
||||
if (existingBean != null) {
|
||||
// advanced case when we use multiple concurrent threads to
|
||||
// build a single object graph, and another thread has since
|
||||
// loaded a matching bean so we will use that instead.
|
||||
ref = existingBean;
|
||||
|
||||
} else {
|
||||
EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept();
|
||||
if (Boolean.TRUE.equals(ctx.isReadOnly())) {
|
||||
ebi.setReadOnly(true);
|
||||
}
|
||||
ctx.register(beanPropertyAssocOne.name, ebi);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
@Override
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
if (beanPropertyAssocOne.targetInheritInfo != null) {
|
||||
// add join to support the discriminator column
|
||||
String relativePrefix = ctx.getRelativePrefix(beanPropertyAssocOne.name);
|
||||
beanPropertyAssocOne.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append columns for foreign key columns.
|
||||
*/
|
||||
@Override
|
||||
void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
|
||||
if (!subQuery && beanPropertyAssocOne.targetInheritInfo != null) {
|
||||
// add discriminator column
|
||||
String relativePrefix = ctx.getRelativePrefix(beanPropertyAssocOne.getName());
|
||||
String tableAlias = ctx.getTableAlias(relativePrefix);
|
||||
ctx.appendColumn(tableAlias, beanPropertyAssocOne.targetInheritInfo.getDiscriminatorColumn());
|
||||
}
|
||||
beanPropertyAssocOne.importedId.sqlAppend(ctx);
|
||||
}
|
||||
}
|
||||
+14
-44
@@ -3,7 +3,6 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
import java.sql.SQLException;
|
||||
@@ -13,55 +12,30 @@ import java.sql.SQLException;
|
||||
*/
|
||||
final class AssocOneHelpReferenceExported extends AssocOneHelp {
|
||||
|
||||
private BeanPropertyAssocOne beanPropertyAssocOne;
|
||||
|
||||
public AssocOneHelpReferenceExported(BeanPropertyAssocOne beanPropertyAssocOne) {
|
||||
this.beanPropertyAssocOne = beanPropertyAssocOne;
|
||||
}
|
||||
|
||||
@Override
|
||||
void loadIgnore(DbReadContext ctx) {
|
||||
beanPropertyAssocOne.targetDescriptor.getIdBinder().loadIgnore(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and set a Reference bean.
|
||||
*/
|
||||
@Override
|
||||
Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
|
||||
|
||||
Object dbVal = read(ctx);
|
||||
if (bean != null) {
|
||||
beanPropertyAssocOne.setValue(bean, dbVal);
|
||||
ctx.propagateState(dbVal);
|
||||
}
|
||||
return dbVal;
|
||||
public AssocOneHelpReferenceExported(BeanPropertyAssocOne property) {
|
||||
super(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object read(DbReadContext ctx) throws SQLException {
|
||||
|
||||
// TODO: Support for Inheritance hierarchy on exported OneToOne ?
|
||||
IdBinder idBinder = beanPropertyAssocOne.targetDescriptor.getIdBinder();
|
||||
Object id = idBinder.read(ctx);
|
||||
// Support for Inheritance hierarchy on exported OneToOne ?
|
||||
Object id = property.targetIdBinder.read(ctx);
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PersistenceContext persistCtx = ctx.getPersistenceContext();
|
||||
Object existing = persistCtx.get(beanPropertyAssocOne.targetType, id);
|
||||
|
||||
PersistenceContext pc = ctx.getPersistenceContext();
|
||||
Object existing = pc.get(property.targetType, id);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
Object ref = beanPropertyAssocOne.targetDescriptor.createReference(ctx.isReadOnly(), id);
|
||||
|
||||
Object ref = property.targetDescriptor.createReference(ctx.isReadOnly(), id);
|
||||
property.targetDescriptor.contextPut(pc, id, ref);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept();
|
||||
if (Boolean.TRUE.equals(ctx.isReadOnly())) {
|
||||
ebi.setReadOnly(true);
|
||||
}
|
||||
beanPropertyAssocOne.targetDescriptor.contextPut(persistCtx, id, ref);
|
||||
ctx.register(beanPropertyAssocOne.name, ebi);
|
||||
ctx.register(property.name, ebi);
|
||||
return ref;
|
||||
}
|
||||
|
||||
@@ -72,20 +46,16 @@ final class AssocOneHelpReferenceExported extends AssocOneHelp {
|
||||
void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
|
||||
// set appropriate tableAlias for the exported id columns
|
||||
|
||||
String relativePrefix = ctx.getRelativePrefix(beanPropertyAssocOne.getName());
|
||||
String relativePrefix = ctx.getRelativePrefix(property.getName());
|
||||
ctx.pushTableAlias(relativePrefix);
|
||||
|
||||
IdBinder idBinder = beanPropertyAssocOne.targetDescriptor.getIdBinder();
|
||||
idBinder.appendSelect(ctx, subQuery);
|
||||
|
||||
property.targetIdBinder.appendSelect(ctx, subQuery);
|
||||
ctx.popTableAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
|
||||
String relativePrefix = ctx.getRelativePrefix(beanPropertyAssocOne.getName());
|
||||
beanPropertyAssocOne.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
String relativePrefix = ctx.getRelativePrefix(property.getName());
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
* The type of bean this describes.
|
||||
*/
|
||||
private final Class<T> beanType;
|
||||
private final Class<?> rootBeanType;
|
||||
protected final Class<?> rootBeanType;
|
||||
|
||||
/**
|
||||
* This is not sent to a remote client.
|
||||
@@ -1528,14 +1528,14 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
}
|
||||
try {
|
||||
EntityBean eb = createEntityBean();
|
||||
|
||||
convertSetId(id, eb);
|
||||
|
||||
EntityBeanIntercept ebi = eb._ebean_getIntercept();
|
||||
ebi.setBeanLoader(ebeanServer);
|
||||
|
||||
// Note: not creating proxies for many's...
|
||||
ebi.setReference(idPropertyIndex);
|
||||
if (Boolean.TRUE == readOnly) {
|
||||
ebi.setReadOnly(true);
|
||||
}
|
||||
|
||||
return (T) eb;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
protected final boolean importedPrimaryKey;
|
||||
|
||||
protected final AssocOneHelp localHelp;
|
||||
protected AssocOneHelp localHelp;
|
||||
|
||||
protected final BeanProperty[] embeddedProps;
|
||||
|
||||
@@ -87,12 +87,13 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
embeddedProps = null;
|
||||
embeddedPropsMap = null;
|
||||
}
|
||||
localHelp = createHelp(embedded, oneToOneExported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise() {
|
||||
super.initialise();
|
||||
localHelp = createHelp(embedded, oneToOneExported);
|
||||
|
||||
if (!isTransient) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
if (embedded) {
|
||||
@@ -633,7 +634,11 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
} else if (oneToOneExported) {
|
||||
return new AssocOneHelpReferenceExported(this);
|
||||
} else {
|
||||
return new AssocOneHelpReference(this);
|
||||
if (targetInheritInfo != null) {
|
||||
return new AssocOneHelpRefInherit(this);
|
||||
} else {
|
||||
return new AssocOneHelpRefSimple(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user