mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-11-12 22:41:35 +00:00
#2174 - Entity beans with @Cache + @DbArray of enums (or UUID or Integer) not converted to enums (come back as String) (#2175)
This commit is contained in:
1 parent
99d7a4e4b4
commit
6aa4337b27
10 files changed
+327
-47
No files matched your search
@@ -10,9 +10,14 @@ import java.util.UUID;
|
||||
interface ArrayElementConverter<T> {
|
||||
|
||||
/**
|
||||
* Convert the array element to the logical type.
|
||||
* Convert element it's json serialized form.
|
||||
*/
|
||||
T toElement(Object rawValue);
|
||||
T fromSerialized(Object rawValue);
|
||||
|
||||
/**
|
||||
* Convert the array element from it's DB array form.
|
||||
*/
|
||||
T fromDbArray(Object rawValue);
|
||||
|
||||
default Object[] toDbArray(Object[] objects) {
|
||||
return objects;
|
||||
@@ -46,7 +51,12 @@ interface ArrayElementConverter<T> {
|
||||
class LongConverter implements ArrayElementConverter<Long> {
|
||||
|
||||
@Override
|
||||
public Long toElement(Object rawValue) {
|
||||
public Long fromSerialized(Object rawValue) {
|
||||
return fromDbArray(rawValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long fromDbArray(Object rawValue) {
|
||||
if (rawValue instanceof Long) {
|
||||
return (Long) rawValue;
|
||||
} else {
|
||||
@@ -58,7 +68,12 @@ interface ArrayElementConverter<T> {
|
||||
class IntegerConverter implements ArrayElementConverter<Integer> {
|
||||
|
||||
@Override
|
||||
public Integer toElement(Object rawValue) {
|
||||
public Integer fromSerialized(Object rawValue) {
|
||||
return ((Number) rawValue).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer fromDbArray(Object rawValue) {
|
||||
if (rawValue instanceof Integer) {
|
||||
return (Integer) rawValue;
|
||||
} else {
|
||||
@@ -70,7 +85,12 @@ interface ArrayElementConverter<T> {
|
||||
class DoubleConverter implements ArrayElementConverter<Double> {
|
||||
|
||||
@Override
|
||||
public Double toElement(Object rawValue) {
|
||||
public Double fromSerialized(Object rawValue) {
|
||||
return fromDbArray(rawValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double fromDbArray(Object rawValue) {
|
||||
if (rawValue instanceof Double) {
|
||||
return (Double) rawValue;
|
||||
} else {
|
||||
@@ -82,21 +102,34 @@ interface ArrayElementConverter<T> {
|
||||
/**
|
||||
* String converter (noop based).
|
||||
*/
|
||||
class StringConverter extends NoopConverter<String> {
|
||||
class StringConverter implements ArrayElementConverter<String> {
|
||||
|
||||
public String fromDbArray(Object rawValue) {
|
||||
return (String) rawValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromSerialized(Object rawValue) {
|
||||
return (String) rawValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UUID converter (noop based).
|
||||
* UUID converter.
|
||||
*/
|
||||
class UuidConverter extends NoopConverter<UUID> {
|
||||
}
|
||||
class UuidConverter implements ArrayElementConverter<UUID> {
|
||||
|
||||
class NoopConverter<T> implements ArrayElementConverter<T> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T toElement(Object rawValue) {
|
||||
return (T) rawValue;
|
||||
public java.util.UUID fromSerialized(Object rawValue) {
|
||||
return java.util.UUID.fromString((String)rawValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.UUID fromDbArray(Object rawValue) {
|
||||
if (rawValue instanceof UUID) {
|
||||
return (java.util.UUID) rawValue;
|
||||
}
|
||||
return java.util.UUID.fromString(rawValue.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +146,12 @@ interface ArrayElementConverter<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toElement(Object rawValue) {
|
||||
public Object fromSerialized(Object rawValue) {
|
||||
return scalarType.parse((String) rawValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fromDbArray(Object rawValue) {
|
||||
return scalarType.toBeanType(rawValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.core.type.ScalarType;
|
||||
|
||||
public class ArrayElementConverterEnum implements ArrayElementConverter<String> {
|
||||
|
||||
final ScalarType<?> scalarType;
|
||||
|
||||
final Class<? extends Enum<?>> valueType1;
|
||||
|
||||
public ArrayElementConverterEnum(ScalarType<?> scalarType, Class<? extends Enum<?>> valueType1) {
|
||||
this.scalarType = scalarType;
|
||||
this.valueType1 = valueType1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toElement(Object rawValue) {
|
||||
// FIXME: Don't understand for what is this.
|
||||
Enum<?>[] enumConstants = valueType1.getEnumConstants();
|
||||
if (scalarType == null) {
|
||||
return rawValue.toString();
|
||||
}
|
||||
return scalarType.format(rawValue);
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements Sc
|
||||
if (element == null) {
|
||||
list.add(null);
|
||||
} else {
|
||||
list.add(converter.toElement(element));
|
||||
list.add(converter.fromDbArray(element));
|
||||
}
|
||||
}
|
||||
return new ModifyAwareList(list);
|
||||
@@ -145,15 +145,27 @@ public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements Sc
|
||||
@Override
|
||||
public List parse(String value) {
|
||||
try {
|
||||
return EJson.parseList(value, false);
|
||||
return convert(EJson.parseList(value, false));
|
||||
} catch (IOException e) {
|
||||
throw new TextException("Failed to parse JSON [{}] as List", value, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from the json types to the proper scalar types (uuid, enum, double etc)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private List convert(List<Object> rawList) {
|
||||
List list = new ArrayList(rawList.size());
|
||||
for (Object rawVal : rawList) {
|
||||
list.add(converter.fromSerialized(rawVal));
|
||||
}
|
||||
return new ModifyAwareList(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List jsonRead(JsonParser parser) throws IOException {
|
||||
return EJson.parseList(parser, parser.getCurrentToken());
|
||||
return convert(EJson.parseList(parser, parser.getCurrentToken()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@@ -101,7 +102,7 @@ public class ScalarTypeArraySet extends ScalarTypeArrayBase<Set> implements Scal
|
||||
protected Set fromArray(Object[] array1) {
|
||||
Set set = new LinkedHashSet();
|
||||
for (Object element : array1) {
|
||||
set.add(converter.toElement(element));
|
||||
set.add(converter.fromDbArray(element));
|
||||
}
|
||||
return new ModifyAwareSet(set);
|
||||
}
|
||||
@@ -140,15 +141,26 @@ public class ScalarTypeArraySet extends ScalarTypeArrayBase<Set> implements Scal
|
||||
@Override
|
||||
public Set parse(String value) {
|
||||
try {
|
||||
return EJson.parseSet(value, false);
|
||||
return convert(EJson.parseList(value, false));
|
||||
} catch (IOException e) {
|
||||
throw new TextException("Failed to parse JSON [{}] as Set", value, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from the json types to the proper scalar types (uuid, enum, double etc)
|
||||
*/
|
||||
private Set convert(List<Object> rawList) {
|
||||
Set asSet = new LinkedHashSet();
|
||||
for (Object rawVal : rawList) {
|
||||
asSet.add(converter.fromSerialized(rawVal));
|
||||
}
|
||||
return new ModifyAwareSet(asSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set jsonRead(JsonParser parser) throws IOException {
|
||||
return EJson.parseSet(parser, parser.getCurrentToken());
|
||||
return convert(EJson.parseList(parser, parser.getCurrentToken()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.core.type.DataReader;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.text.json.EJson;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -63,4 +68,82 @@ public class ScalarTypeArrayListTest extends BasePlatformArrayTypeFactoryTest {
|
||||
assertBindNullTo_Null(factory.typeFor(UUID.class, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void parse_withUuidType_expect_uuidTypeReturned() {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(UUID.class, true);
|
||||
|
||||
List<UUID> input = new ArrayList<>();
|
||||
input.add(UUID.randomUUID());
|
||||
input.add(UUID.randomUUID());
|
||||
|
||||
String formatToJson = scalarType.format(input);
|
||||
|
||||
Object parsed = scalarType.parse(formatToJson);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void parse_withIntegerType_expect_longIntegerReturned() {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(Integer.class, true);
|
||||
|
||||
List<Integer> input = new ArrayList<>();
|
||||
input.add(2);
|
||||
input.add(4);
|
||||
|
||||
String formatToJson = scalarType.format(input);
|
||||
|
||||
Object parsed = scalarType.parse(formatToJson);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void parse_withLongType_expect_longTypeReturned() {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(Long.class, true);
|
||||
|
||||
List<Long> input = new ArrayList<>();
|
||||
input.add(2L);
|
||||
input.add(4L);
|
||||
|
||||
String formatToJson = scalarType.format(input);
|
||||
|
||||
Object parsed = scalarType.parse(formatToJson);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_withDoubleType_expect_longTypeReturned() {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(Double.class, true);
|
||||
|
||||
List<Double> input = new ArrayList<>();
|
||||
input.add(2D);
|
||||
input.add(4D);
|
||||
|
||||
String formatToJson = scalarType.format(input);
|
||||
|
||||
Object parsed = scalarType.parse(formatToJson);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jsonRead_withUuidType() throws IOException {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(UUID.class, true);
|
||||
|
||||
List<UUID> input = new ArrayList<>();
|
||||
input.add(UUID.randomUUID());
|
||||
input.add(UUID.randomUUID());
|
||||
String asJson = EJson.write(input);
|
||||
|
||||
JsonParser parser = DB.json().createParser(new StringReader(asJson));
|
||||
|
||||
Object parsed = scalarType.jsonRead(parser);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,16 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.text.json.EJson;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -49,4 +57,82 @@ public class ScalarTypeArraySetH2Test extends BasePlatformArrayTypeFactoryTest {
|
||||
assertBindNullTo_Null(factory.typeFor(UUID.class, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void parse_withUuidType_expect_uuidTypeReturned() {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(UUID.class, true);
|
||||
|
||||
Set<UUID> input = new LinkedHashSet<>();
|
||||
input.add(UUID.randomUUID());
|
||||
input.add(UUID.randomUUID());
|
||||
|
||||
String formatToJson = scalarType.format(input);
|
||||
|
||||
Set<UUID> parsed = (Set<UUID>)scalarType.parse(formatToJson);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void parse_withIntegerType_expect_longIntegerReturned() {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(Integer.class, true);
|
||||
|
||||
Set<Integer> input = new LinkedHashSet<>();
|
||||
input.add(2);
|
||||
input.add(4);
|
||||
|
||||
String formatToJson = scalarType.format(input);
|
||||
|
||||
Set<Integer> parsed = (Set<Integer>)scalarType.parse(formatToJson);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void parse_withLongType_expect_longTypeReturned() {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(Long.class, true);
|
||||
|
||||
Set<Long> input = new LinkedHashSet<>();
|
||||
input.add(2L);
|
||||
input.add(4L);
|
||||
|
||||
String formatToJson = scalarType.format(input);
|
||||
|
||||
Set<Long> parsed = (Set<Long>)scalarType.parse(formatToJson);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_withDoubleType_expect_longTypeReturned() {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(Double.class, true);
|
||||
|
||||
Set<Double> input = new LinkedHashSet<>();
|
||||
input.add(2D);
|
||||
input.add(4D);
|
||||
|
||||
String formatToJson = scalarType.format(input);
|
||||
|
||||
Object parsed = scalarType.parse(formatToJson);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jsonRead_withUuidType() throws IOException {
|
||||
|
||||
ScalarType<?> scalarType = factory.typeFor(UUID.class, true);
|
||||
|
||||
Set<UUID> input = new LinkedHashSet<>();
|
||||
input.add(UUID.randomUUID());
|
||||
input.add(UUID.randomUUID());
|
||||
String asJson = EJson.write(input);
|
||||
|
||||
JsonParser parser = DB.json().createParser(new StringReader(asJson));
|
||||
|
||||
Object parsed = scalarType.jsonRead(parser);
|
||||
assertThat(parsed).isEqualTo(input);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.tests.model.array;
|
||||
|
||||
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.annotation.DbArray;
|
||||
import io.ebean.annotation.NotNull;
|
||||
|
||||
@@ -13,6 +14,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Cache
|
||||
public class EArrayBean {
|
||||
|
||||
enum Status {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.tests.model.array;
|
||||
|
||||
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.annotation.DbArray;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
@@ -11,6 +12,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Cache
|
||||
public class EArraySetBean {
|
||||
|
||||
@Id
|
||||
@@ -30,6 +32,9 @@ public class EArraySetBean {
|
||||
@DbArray
|
||||
Set<Double> doubs;
|
||||
|
||||
@DbArray
|
||||
Set<EArrayBean.Status> status;
|
||||
|
||||
@Version
|
||||
Long version;
|
||||
|
||||
@@ -81,6 +86,14 @@ public class EArraySetBean {
|
||||
this.doubs = doubs;
|
||||
}
|
||||
|
||||
public Set<EArrayBean.Status> getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Set<EArrayBean.Status> status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,11 @@ public class TestDbArray_asSet extends BaseTestCase {
|
||||
bean.getOtherIds().add(97L);
|
||||
bean.setDoubs(doubles);
|
||||
|
||||
Set<EArrayBean.Status> status = new LinkedHashSet<>();
|
||||
status.add(EArrayBean.Status.ONE);
|
||||
status.add(EArrayBean.Status.TWO);
|
||||
bean.setStatus(status);
|
||||
|
||||
Ebean.save(bean);
|
||||
|
||||
found = Ebean.find(EArraySetBean.class, bean.getId());
|
||||
@@ -154,4 +159,31 @@ public class TestDbArray_asSet extends BaseTestCase {
|
||||
Ebean.saveAll(all);
|
||||
Ebean.deleteAll(all);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.HANA)
|
||||
public void hitCache() {
|
||||
|
||||
Set<UUID> uids = new LinkedHashSet<>();
|
||||
uids.add(UUID.randomUUID());
|
||||
uids.add(UUID.randomUUID());
|
||||
|
||||
Set<EArrayBean.Status> statuses = new LinkedHashSet<>();
|
||||
statuses.add(EArrayBean.Status.ONE);
|
||||
statuses.add(EArrayBean.Status.THREE);
|
||||
|
||||
EArraySetBean bean = new EArraySetBean();
|
||||
bean.setName("hitCache");
|
||||
bean.setUids(uids);
|
||||
bean.setStatus(statuses);
|
||||
|
||||
Ebean.save(bean);
|
||||
// load cache
|
||||
Ebean.find(EArraySetBean.class, bean.getId());
|
||||
// hit cache
|
||||
EArraySetBean found = Ebean.find(EArraySetBean.class, bean.getId());
|
||||
|
||||
assertThat(found.getUids()).isEqualTo(uids);
|
||||
assertThat(found.getStatus()).isEqualTo(statuses);
|
||||
}
|
||||
}
|
||||
@@ -249,4 +249,31 @@ public class TestDbArray_basic extends BaseTestCase {
|
||||
assertThat(found.getIntEnums()).containsExactly(null, IntEnum.ZERO, null, IntEnum.TWO);
|
||||
Ebean.delete(bean);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.HANA)
|
||||
public void hitCache() {
|
||||
|
||||
List<UUID> uids = new ArrayList<>();
|
||||
uids.add(UUID.randomUUID());
|
||||
uids.add(UUID.randomUUID());
|
||||
|
||||
List<EArrayBean.Status> statuses = new ArrayList<>();
|
||||
statuses.add(EArrayBean.Status.ONE);
|
||||
statuses.add(EArrayBean.Status.THREE);
|
||||
|
||||
EArrayBean bean = new EArrayBean();
|
||||
bean.setName("hitCache");
|
||||
bean.setUids(uids);
|
||||
bean.setStatuses(statuses);
|
||||
|
||||
Ebean.save(bean);
|
||||
// load cache
|
||||
Ebean.find(EArrayBean.class, bean.getId());
|
||||
// hit cache
|
||||
EArrayBean found = Ebean.find(EArrayBean.class, bean.getId());
|
||||
|
||||
assertThat(found.getUids()).isEqualTo(uids);
|
||||
assertThat(found.getStatuses()).isEqualTo(statuses);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user