Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
private Map<Class<?>, DeployBeanInfo<?>> deployInfoMap = new HashMap<>();
private Set<Class<?>> embeddedIdTypes = new HashSet<>();
private List<DeployBeanInfo<?>> embeddedBeans = new ArrayList<>();
private final List<CustomPair> customizedEntities = new ArrayList<>();

/**
* Create for a given database dbConfig.
Expand Down Expand Up @@ -511,6 +512,11 @@ private void initialiseAll() {
checkForValidEmbeddedId(d);
}
}
//for (CustomPair pair : customizedEntities) {
//BeanManager<?> newDesc = beanManagerMap.get(pair.overrideType.getName());
//BeanManager<?> oldDesc = beanManagerMap.get(pair.originalType.getName());
// System.out.println("replaced " + oldDesc + " with " + newDesc);
//}
}

private void checkForValidEmbeddedId(BeanDescriptor<?> d) {
Expand Down Expand Up @@ -618,7 +624,16 @@ public <T> DeployBeanInfo<T> deploy(Class<T> cls) {

private void registerDescriptor(DeployBeanInfo<?> info) {
BeanDescriptor<?> desc = new BeanDescriptor<>(this, info.getDescriptor());
if (info.isCustomized()) {
// register for persisting via BeanManager which will use this descriptor
descMap.put("customized:" + desc.type().getName(), desc);
return;
}
descMap.put(desc.type().getName(), desc);
Class<?> originalType = info.getOriginalType();
if (originalType != null) {
descMap.put(originalType.getName(), desc);
}
if (desc.isDocStoreMapped()) {
descQueueMap.put(desc.docStoreQueueId(), desc);
}
Expand Down Expand Up @@ -657,6 +672,10 @@ private void readEntityDeploymentInitial() {
embeddedBeans.add(info);
}
}
for (CustomPair pair : customizedEntities) {
DeployBeanInfo<?> info = deployInfoMap.get(pair.originalType);
info.markAsCustomized();
}
}

private void registerEmbeddedBean(DeployBeanInfo<?> info) {
Expand All @@ -671,8 +690,14 @@ private void registerEmbeddedBean(DeployBeanInfo<?> info) {
*/
private void readEntityBeanTable() {
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
BeanTable beanTable = createBeanTable(info);
beanTableMap.put(beanTable.getBeanType(), beanTable);
if (!info.isCustomized()) {
BeanTable beanTable = createBeanTable(info);
beanTableMap.put(beanTable.getBeanType(), beanTable);
Class<?> originalType = info.getOriginalType();
if (originalType != null) {
beanTableMap.put(originalType, beanTable);
}
}
}
// register non-id embedded beans (after bean tables are created)
for (DeployBeanInfo<?> info : embeddedBeans) {
Expand Down Expand Up @@ -1506,6 +1531,13 @@ public List<MetaQueryPlan> queryPlanInit(QueryPlanInit request) {
return list;
}

/**
* Register that entity overrideType extends/customizes the originalType entity.
*/
public void addCustomizedEntity(Class<?> overrideType, Class<?> originalType) {
customizedEntities.add(new CustomPair(overrideType, originalType));
}

/**
* Comparator to sort the BeanDescriptors by name.
*/
Expand All @@ -1518,4 +1550,15 @@ public int compare(BeanDescriptor<?> o1, BeanDescriptor<?> o2) {
return o1.name().compareTo(o2.name());
}
}

private static final class CustomPair {

final Class<?> overrideType;
final Class<?> originalType;

CustomPair(Class<?> overrideType, Class<?> originalType) {
this.overrideType = overrideType;
this.originalType = originalType;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,14 @@
import io.ebean.config.TableName;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.PlatformIdGenerator;
import io.ebean.event.BeanFindController;
import io.ebean.event.BeanPersistController;
import io.ebean.event.BeanPersistListener;
import io.ebean.event.BeanPostConstructListener;
import io.ebean.event.BeanPostLoad;
import io.ebean.event.BeanQueryAdapter;
import io.ebean.event.*;
import io.ebean.event.changelog.ChangeLogFilter;
import io.ebean.text.PathProperties;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.ConcurrencyMode;
import io.ebeaninternal.server.core.CacheOptions;
import io.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeaninternal.server.deploy.ChainedBeanPersistController;
import io.ebeaninternal.server.deploy.ChainedBeanPersistListener;
import io.ebeaninternal.server.deploy.ChainedBeanPostConstructListener;
import io.ebeaninternal.server.deploy.ChainedBeanPostLoad;
import io.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
import io.ebeaninternal.server.deploy.DeployPropertyParserMap;
import io.ebeaninternal.server.deploy.IdentityMode;
import io.ebeaninternal.server.deploy.IndexDefinition;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.PartitionMeta;
import io.ebeaninternal.server.deploy.TableJoin;
import io.ebeaninternal.server.deploy.TablespaceMeta;
import io.ebeaninternal.server.deploy.*;
import io.ebeaninternal.server.deploy.parse.DeployBeanInfo;
import io.ebeaninternal.server.idgen.UuidV1IdGenerator;
import io.ebeaninternal.server.idgen.UuidV1RndIdGenerator;
Expand All @@ -41,13 +24,7 @@

import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

/**
* Describes Beans including their deployment information.
Expand Down Expand Up @@ -118,6 +95,8 @@ public int compare(DeployBeanProperty o1, DeployBeanProperty o2) {
* The EntityBean type used to create new EntityBeans.
*/
private final Class<T> beanType;
private Class<?> originalType;
private boolean customized;
private final List<BeanPersistController> persistControllers = new ArrayList<>();
private final List<BeanPersistListener> persistListeners = new ArrayList<>();
private final List<BeanQueryAdapter> queryAdapters = new ArrayList<>();
Expand Down Expand Up @@ -254,7 +233,7 @@ public PartitionMeta getPartitionMeta() {
}
return partitionMeta;
}

public void setTablespaceMeta(TablespaceMeta tablespaceMeta) {
this.tablespaceMeta = tablespaceMeta;
}
Expand Down Expand Up @@ -312,11 +291,9 @@ public boolean isScalaObject() {
}

public DeployBeanTable createDeployBeanTable() {

DeployBeanTable beanTable = new DeployBeanTable(getBeanType());
DeployBeanTable beanTable = new DeployBeanTable(beanType);
beanTable.setBaseTable(baseTable);
beanTable.setIdProperty(idProperty());

return beanTable;
}

Expand Down Expand Up @@ -392,6 +369,20 @@ public void setProperties(String[] props) {
this.properties = props;
}

public boolean isCustomized() {
return customized;
}

public void markAsCustomized() {
this.customized = true;
this.entityType = EntityType.VIEW;
this.dependentTables = new String[]{baseTable};
}

public Class<?> getOriginalType() {
return originalType;
}

/**
* Return the class type this BeanDescriptor describes.
*/
Expand Down Expand Up @@ -976,15 +967,18 @@ public void checkInheritanceMapping() {
* Check valid mapping annotations on the class hierarchy.
*/
private void checkInheritance(Class<?> beanType) {

Class<?> parent = beanType.getSuperclass();
if (parent == null || Object.class.equals(parent)) {
// all good
return;
}
if (parent.isAnnotationPresent(Entity.class)) {
String msg = "Checking " + getBeanType() + " and found " + parent + " that has @Entity annotation rather than MappedSuperclass?";
throw new IllegalStateException(msg);
// String msg = "Checking " + getBeanType() + " and found " + parent + " that has @Entity annotation rather than MappedSuperclass?";
// throw new IllegalStateException(msg);
// allow an entity to extend an entity ... as "customization"
originalType = parent;
manager.addCustomizedEntity(beanType, parent);
return;
}
if (parent.isAnnotationPresent(MappedSuperclass.class)) {
// continue checking
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,16 @@ public Class<?> getEmbeddedIdType() {
public boolean isEmbedded() {
return descriptor.isEmbedded();
}

public Class<?> getOriginalType() {
return descriptor.getOriginalType();
}

public void markAsCustomized() {
descriptor.markAsCustomized();
}

public boolean isCustomized() {
return descriptor.isCustomized();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import io.ebean.annotation.Cache;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Cache(naturalKey = "appName")
@Entity
@Table(name="ocached_app")
@UniqueConstraint(name="uq_ocached_app", columnNames = "app_name")
public class OCachedApp extends OCacheBase {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.tests.model.basic.cache;

import io.ebean.annotation.Cache;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Cache(naturalKey = "appName")
@Entity
@Table(name = "ocached_app")
@UniqueConstraint(name = "uq_ocached_app", columnNames = "app_name")
public class OCachedAppCustom extends OCachedApp {

String custom;

public OCachedAppCustom(String appName) {
super(appName);
}

public String getCustom() {
return custom;
}

public void setCustom(String custom) {
this.custom = custom;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.tests.model.basic.cache;

import io.ebean.DB;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

class TestCustomExtends {

@Test
void insert_find() {
OCachedApp orig = new OCachedApp("orig");
DB.save(orig);

OCachedAppCustom custom = new OCachedAppCustom("custom");
custom.setCustom("someCustomValue");
DB.save(custom);

OCachedAppCustom c1 = DB.find(OCachedAppCustom.class, custom.getId());
OCachedApp c2 = DB.find(OCachedApp.class, custom.getId());

OCachedAppCustom o1 = DB.find(OCachedAppCustom.class, orig.getId());
OCachedApp o2 = DB.find(OCachedApp.class, orig.getId());

assertThat(c1).isNotNull();
assertThat(c2).isNotNull();
assertThat(c2.getAppName()).isEqualTo(c1.getAppName());
assertThat(c2).isNotNull().isInstanceOf(OCachedAppCustom.class);

assertThat(o1).isNotNull();
assertThat(o2).isNotNull();
assertThat(o2.getAppName()).isEqualTo(o1.getAppName());
assertThat(o2).isNotNull().isInstanceOf(OCachedAppCustom.class);
}
}