#852 - javax.persistence.PersistenceException: No ScalarType registered for class Foo$1 ... where Foo is an Enum where individual instances override a method (example below).

This commit is contained in:
Rob Bygrave
2016-11-06 20:33:56 +13:00
parent d84080fb76
commit 2a6d38eef2
6 changed files with 85 additions and 20 deletions
@@ -119,14 +119,15 @@ public class DeployUtil {
ScalarType<?> scalarType = typeManager.getScalarType(enumType);
if (scalarType == null) {
// look for @DbEnumValue or @EnumValue annotations etc
scalarType = typeManager.createEnumScalarType((Class<? extends Enum<?>>)enumType);
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>)enumType;
scalarType = typeManager.createEnumScalarType(enumClass);
if (scalarType == null) {
// use JPA normal Enum type (without mapping)
EnumType type = enumerated != null ? enumerated.value() : null;
scalarType = createEnumScalarTypePerSpec(enumType, type);
}
typeManager.add(scalarType);
typeManager.addEnumType(scalarType, enumClass);
}
prop.setScalarType(scalarType);
prop.setDbType(scalarType.getJdbcType());
@@ -62,19 +62,7 @@ import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Currency;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -330,6 +318,24 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
logAdd(scalarType);
}
/**
* Register the ScalarType for an enum. This is special in the sense that an Enum
* can have many classes if it uses method overrides and we need to register all
* the variations/classes for the enum.
*/
@Override
public void addEnumType(ScalarType<?> scalarType, Class<? extends Enum> enumClass) {
Set<Class<?>> mappedClasses = new HashSet<>();
for (Object value : EnumSet.allOf(enumClass).toArray()) {
mappedClasses.add(value.getClass());
}
for (Class<?> cls: mappedClasses) {
typeMap.put(cls, scalarType);
}
logAdd(scalarType);
}
private void logAdd(ScalarType<?> scalarType) {
if (logger.isDebugEnabled()) {
String msg = "ScalarType register [" + scalarType.getClass().getName() + "]";
@@ -30,6 +30,11 @@ public interface TypeManager {
*/
void add(ScalarType<?> scalarType);
/**
* Register a ScalarType for an Enum with can have multiple classes.
*/
void addEnumType(ScalarType<?> type, Class<? extends Enum> myEnumClass);
/**
* Return the Internal CompoundType handler for a given compound type.
*/
@@ -0,0 +1,28 @@
package com.avaje.ebean.server.type;
import com.avaje.ebean.annotation.EnumValue;
/**
* Enum with method overrides (and hence multiple actual classes).
*/
public enum MyEnum {
@EnumValue("A")Aval {
@Override
public String doSomething() {
return "bar";
}
},
@EnumValue("B")Bval,
@EnumValue("C")Cval {
@Override
public String doSomething() {
return "baz";
}
};
public String doSomething() {
return "foo";
}
}
@@ -23,6 +23,31 @@ import static org.assertj.core.api.Assertions.assertThat;
public class TestTypeManager extends BaseTestCase {
@Test
public void testEnumWithSubclasses() throws SQLException {
DefaultTypeManager typeManager = createTypeManager();
ScalarType<?> type = typeManager.createEnumScalarType(MyEnum.class);
typeManager.addEnumType(type, MyEnum.class);
Object val = type.read(new DummyDataReader("A"));
assertThat(val).isEqualTo(MyEnum.Aval);
val = type.read(new DummyDataReader("B"));
assertThat(val).isEqualTo(MyEnum.Bval);
val = type.read(new DummyDataReader("C"));
assertThat(val).isEqualTo(MyEnum.Cval);
ScalarType<?> typeGeneral = typeManager.getScalarType(MyEnum.class);
assertThat(typeGeneral).isNotNull();
ScalarType<?> typeB = typeManager.getScalarType(MyEnum.Bval.getClass());
assertThat(typeB).isNotNull();
ScalarType<?> typeA = typeManager.getScalarType(MyEnum.Aval.getClass());
assertThat(typeA).isNotNull();
ScalarType<?> typeC = typeManager.getScalarType(MyEnum.Cval.getClass());
assertThat(typeC).isNotNull();
}
@Test
public void testEnumWithChar() throws SQLException {
@@ -88,7 +113,7 @@ public class TestTypeManager extends BaseTestCase {
String val;
public DummyDataReader(String val) {
DummyDataReader(String val) {
super(null, null);
this.val = val;
}
+4 -4
View File
@@ -78,10 +78,10 @@
<logger name="com.avaje.ebean" level="INFO"/>
<logger name="org.avaje.ebean" level="INFO"/>
<logger name="org.avaje.ebean.SQL" level="TRACE"/>
<logger name="org.avaje.ebean.TXN" level="TRACE"/>
<logger name="org.avaje.ebean.SUM" level="TRACE"/>
<logger name="org.avaje.ebean.ELA" level="TRACE"/>
<!--<logger name="org.avaje.ebean.SQL" level="TRACE"/>-->
<!--<logger name="org.avaje.ebean.TXN" level="TRACE"/>-->
<!--<logger name="org.avaje.ebean.SUM" level="TRACE"/>-->
<!--<logger name="org.avaje.ebean.ELA" level="TRACE"/>-->
<!--<logger name="org.avaje.ebean.cache.QUERY" level="TRACE"/>-->
<!--<logger name="org.avaje.ebean.cache.BEAN" level="TRACE"/>-->