How to map custom enumerated integer ordinals with hibernate? - java

I have an enum class named Status as follows
public enum Status {
PENDING(0), SUCCESS(1), FAILED(-1);
private int st;
private Status(int st){
this.st = st;
}
}
and from other class I try to map this status enum
public void setStatus(Status status) {
this.status = status;
}
#Enumerated(EnumType.ORDINAL)
public Status getStatus() {
return status;
}
when I run this code, I get
java.lang.IllegalArgumentException: Unknown ordinal value for enum class data.Status: -1
at org.hibernate.type.EnumType.nullSafeGet(EnumType.java:93)
at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:124)
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:106)
at
but I already have -1 in enum definition.

You could define your own UserType which defines how Hibernate should map those enums.
Note that the ordinal defines the index of the enum value and thus FAILED would have the ordinal 2. To map the enum using its properties your need a UserType implementation.
Some links:
https://community.jboss.org/wiki/UserTypeForPersistingAnEnumWithAVARCHARColumn
http://javadata.blogspot.de/2011/07/hibernate-and-enum-handling.html (look at the "Paramterized Enumeration in Hibernate" section)

Here is a solution where a string label is used instead of an int id, however it is simple to adapt.
public class User {
#Id
private int id;
#Type(type = "com.example.hibernate.LabeledEnumType")
private Role role;
}
public enum Role implements LabeledEnum {
ADMIN("admin"), USER("user"), ANONYMOUS("anon");
private final String label;
Role(String label) {
this.label = label;
}
#Override
public String getLabel() {
return label;
}
}
public interface LabeledEnum {
String getLabel();
}
public final class LabeledEnumType implements DynamicParameterizedType, UserType {
private Class<? extends Enum> enumClass;
#Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
#Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
#Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
#Override
public boolean equals(Object x, Object y) throws HibernateException {
return x == y;
}
#Override
public int hashCode(Object x) throws HibernateException {
return x == null ? 0 : x.hashCode();
}
#Override
public boolean isMutable() {
return false;
}
#Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
String label = rs.getString(names[0]);
if (rs.wasNull()) {
return null;
}
for (Enum value : returnedClass().getEnumConstants()) {
if (value instanceof LabeledEnum) {
LabeledEnum labeledEnum = (LabeledEnum) value;
if (labeledEnum.getLabel().equals(label)) {
return value;
}
}
}
throw new IllegalStateException("Unknown " + returnedClass().getSimpleName() + " label");
}
#Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.VARCHAR);
} else {
st.setString(index, ((LabeledEnum) value).getLabel());
}
}
#Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
#Override
public Class<? extends Enum> returnedClass() {
return enumClass;
}
#Override
public int[] sqlTypes() {
return new int[]{Types.VARCHAR};
}
#Override
public void setParameterValues(Properties parameters) {
ParameterType params = (ParameterType) parameters.get( PARAMETER_TYPE );
enumClass = params.getReturnedClass();
}
}

I would like to suggest following workaround. At first I was supprised it worked but it is really simple:
For enum:
public enum Status {
PENDING(0), SUCCESS(1), FAILED(-1);
private int status;
private Status(int status){
this.status = status;
}
public String getStatus() {
return status;
}
public static Status parse(int id) {
Status status = null; // Default
for (Status item : Status.values()) {
if (item.getStatus().equals(id)) {
Status = item;
break;
}
}
return Status;
}
}
class
class StatedObject{
#Column("status")
private int statusInt;
public Status getStatus() {
return Status.parse(statusInt);
}
public void setStatus(Status paymentStatus) {
this.statusInt = paymentStatus.getStatus();
}
public String getStatusInt() {
return statusInt;
}
public void setStatusInt(int statusInt) {
this.statusInt = statusInt;
}
}
if you are using hibernate in hibernate xml file it would be:
<property name="statusInt " column="status" type="java.lang.Integer" />
that is it

Related

Java hibernate conditionally apply annotation to a field?

Scenario: A data object which persists in the DB table. There are some old entries in the table. Now I have to apply encryption to new further entries in the table. So I add a new column which has the field encrypted set to False by default to check if the values are encrypted.
Problem: I want to write an annotation to encrypt the fields in the data model(POJO) before persisting and decrypt on getter() calls only if it is encrypted.
Context:
The user model.
public class UserData {
#Id
#Column(name = "ID", length = 36)
private String id;
#Column(name = "IS_ENCRYPTED")
private boolean isEncrypted;
#Column(name = "NAME")
#Convert(converter = EncryptionConverter.class)
private String name;
// more fields ....
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
// more similar getter and setters
}
The encryption class that i have written.
#Converter
public class EncryptionConverter implements AttributeConverter<String, String>{
private final String secretKey= "someSecret";
UserData Data = new UserData();
#Override
public String convertToDatabaseColumn(String str) {
if(!isNullOrBlank(str))
return AesEncrypt.encrypt(str, secretKey);
return str;
}
#Override
public String convertToEntityAttribute(String encrypedStr) {
if(!isNullOrBlank(encrypedStr) && Data.isEncrypted)
return AesEncrypt.decrypt(encrypedStr, secretKey);
return encrypedStr;
}
}
This class is inside the model class. (can move outside, but how to pass isencrypted flag to annotation)
How can I do this, is my approach correct?
Edit: there are multiple fields which are to be encrypted/decrypted not just name.
You can create the encryption behaviour in another configuration class, say EncryptedPropertyConfig, in this you can create a bean, EncryptablePropertyResolver from jasypt-spring-boot
#EnableAutoConfiguration
public class EncryptedPropertyConfig {
public EncryptedPropertyConfig() {
}
#Bean
public EncryptablePropertyResolver encryptablePropertyResolver() {
EncryptablePropertyResolver r = new MyPropertyPlaceholderConfigurer();
return r;
}
}
public final class MyPropertyPlaceholderConfigurer implements EncryptablePropertyResolver {
private StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
private EnvironmentStringPBEConfig envConfig = new EnvironmentStringPBEConfig();
public MyPropertyPlaceholderConfigurer() {
// set the encryption key and config
}
public String resolvePropertyValue(String passedValue) {
if (!PropertyValueEncryptionUtils.isEncryptedValue(passedValue)) {
return passedValue;
} else {
String returnValue = "";
try {
returnValue = PropertyValueEncryptionUtils.decrypt(passedValue, this.encryptor);
return returnValue;
} catch (Exception var4) {
throw new RuntimeException("Error in decryption of property value:" + passedValue, var4);
}
}
}
}
I suggest alternative solution using Entity Listeners
import javax.persistence.PostLoad;
import javax.persistence.PreUpdate;
public class UserData {
private final String secretKey= "someSecret";
// ...
#PreUpdate
private void onUpdate() {
// triggered before saving entity to DB (both create & update)
if(!isNullOrBlank(name)) {
name = AesEncrypt.encrypt(name, secretKey);
}
}
#PostLoad
private void onLoad() {
// triggered after entity is fetched from Entity Provider
if (!isNullOrBlank(name) && isEncrypted) {
name = AesEncrypt.decrypt(name, secretKey);
}
}
}
Instead of using JPA AttributeConverter you can implement hibernate user type in this way:
import java.util.Objects;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.StringType;
import org.hibernate.usertype.UserType;
public class CustomNameType implements UserType
{
private String secretKey = "someSecret";
public CustomNameType()
{
}
#Override
public Object deepCopy(Object value) throws HibernateException
{
if (null == value) return null;
return ((CustomName) value).clone();
}
#Override
public Object assemble(Serializable cached, Object owner) throws HibernateException
{
return cached;
}
#Override
public Serializable disassemble(Object value) throws HibernateException
{
return (Serializable) value;
}
#Override
public Object replace(Object original, Object target, Object owner) throws HibernateException
{
return original;
}
#Override
public boolean equals(Object one, Object two) throws HibernateException
{
return Objects.equals(one, two);
}
#Override
public int hashCode(Object obj) throws HibernateException
{
return Objects.hashCode(obj);
}
#Override
public boolean isMutable()
{
return true;
}
#Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException
{
boolean isEncrypted = rs.getBoolean(0); // IS_ENCRYPTED
String name = rs.getString(1); // NAME
if (isEncrypted) {
name = AesEncrypt.decrypt(name, secretKey);
}
return new CustomName(isEncrypted, name);
}
#Override
public void nullSafeSet(PreparedStatement statement, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException
{
CustomName customName = (CustomName) value;
String name = customName.getName();
if (customName.isEncrypted()) {
name = AesEncrypt.encrypt(name, secretKey);
}
statement.setBoolean(0, customName.isEncrypted());
statement.setString(1, name);
}
#Override
public Class<?> returnedClass()
{
return CustomName.class;
}
#Override
public int[] sqlTypes()
{
// I do not know the types of your IS_ENCRYPTED and NAME fields
// So, this place maybe require correction
int[] types = {BooleanType.INSTANCE.sqlType(), StringType.INSTANCE.sqlType()};
return types;
}
}
where CustomName is:
public class CustomName implements Serializable, Cloneable
{
private boolean isEncrypted;
private String name;
public CustomName(boolean isEncrypted, String name)
{
this.isEncrypted = isEncrypted;
this.name = name;
}
// getters , equals, hashCode ...
#Override
public CustomName clone()
{
return new CustomName(isEncrypted, name);
}
}
and then use it:
import org.hibernate.annotations.Type;
import org.hibernate.annotations.Columns;
#Entity
public class UserData {
#Type(type = "com.your.CustomNameType")
#Columns(columns = {
#Column(name = "IS_ENCRYPTED"),
#Column(name = "NAME")
})
private CustomName name;
}

Realm and Expected BEGIN_OBJECT but was NUMBER at path $[0].location.coordinates[0]

I'm trying to store a coordnates (array of double) using Realm-java,but I'm not able to do it.
Here is an example of json that I'm trying to parse:
{"_id":"597cd98b3af0b6315576d717",
"comarca":"string",
"font":null,
"imatge":"string",
"location":{
"coordinates":[41.64642,1.1393],
"type":"Point"
},
"marca":"string",
"municipi":"string",
"publisher":"string",
"recursurl":"string",
"tematica":"string",
"titol":"string"
}
My global object code is like that
public class Images extends RealmObject implements Serializable {
#PrimaryKey
private String _id;
private String recursurl;
private String titol;
private String municipi;
private String comarca;
private String marca;
private String imatge;
#Nullable
private Location location;
private String tematica;
private String font;
private String parentRoute;
public Location getLocation() {return location;}
public void setLocation(Location location) {this.location = location;}
public String getParentRoute() {
return parentRoute;
}
public void setParentRoute(String parentRoute) {
this.parentRoute = parentRoute;
}
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getFont() {
return font;
}
public void setFont(String font) {
this.font = font;
}
public String getRecursurl() {
return recursurl;
}
public void setRecursurl(String recursurl) {
this.recursurl = recursurl;
}
public String getTitol() {
return titol;
}
public void setTitol(String titol) {
this.titol = titol;
}
public String getMunicipi() {
return municipi;
}
public void setMunicipi(String municipi) {
this.municipi = municipi;
}
public String getComarca() {
return comarca;
}
public void setComarca(String comarca) {
this.comarca = comarca;
}
public String getMarca() {
return marca;
}
public void setMarca(String marca) {
this.marca = marca;
}
public String getImatge() {
return imatge;
}
public void setImatge(String imatge) {
this.imatge = imatge;
}
public String getTematica() {
return tematica;
}
public void setTematica(String tematica) {
this.tematica = tematica;
}
And Location is a composite of type and a realmlist
Location.java
public class Location extends RealmObject implements Serializable {
private String type;
private RealmList<RealmDoubleObject> coordinates;
public Location() {
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public RealmList<RealmDoubleObject> getCoordinates() {
return coordinates;
}
public void setCoordinates(RealmList<RealmDoubleObject> coordinates) {
this.coordinates = coordinates;
}
}
RealmDoubleObject.java
public class RealmDoubleObject extends RealmObject implements Serializable{
private Double value;
public RealmDoubleObject() {
}
public Double getDoublevalue() {
return value;
}
public void setDoublevalue(Double value) {
this.value = value;
}
}
The error is com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at path $[0].location.coordinates[0] but I'm not able to figure out why this number is not "fitting" by RealmDoubleObject.
For those that not familiar with realm RealmList doesn't work and you have to build your own realm object.
Thank you. I hope to find some Realm experts here!
SOLVED:
using Gson deserializer it can be done
First we have to initialize the gson object like this
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
#Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
})
.registerTypeAdapter(new TypeToken<RealmList<RealmDoubleObject>>() {}.getType(), new TypeAdapter<RealmList<RealmDoubleObject>>() {
#Override
public void write(JsonWriter out, RealmList<RealmDoubleObject> value) throws IOException {
// Ignore
}
#Override
public RealmList<RealmDoubleObject> read(JsonReader in) throws IOException {
RealmList<RealmDoubleObject> list = new RealmList<RealmDoubleObject>();
in.beginArray();
while (in.hasNext()) {
Double valor = in.nextDouble();
list.add(new RealmDoubleObject(valor));
}
in.endArray();
return list;
}
})
.create();
And then we have to put some other constructor method
public RealmDoubleObject(double v) {
this.value = v;
}
and this is all.
Thanks for the help #EpicPandaForce

Case insensitive Enum-Mapping with Hibernate

I got an entity with a column state. States stored in the DB are active and inactive (and some more). I wrote myself an enum like the following
public enum State {
ACTIVE("active"), INACTIVE("inactive");
private String state;
private State(String state) {
this.state = state;
}
}
The entity looks like:
#Entity
#Table(name = "TEST_DB")
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ID")
private Integer id;
#Enumerated(EnumType.STRING)
#Column(name = "STATE", nullable = false)
private Integer state;
// constructor, getter, setter
}
Unfortunately I get the following error message:
javax.ejb.EJBTransactionRolledbackException: Unknown name value [active] for enum class [state]
Is it possible to do a case-insensitive hibernate-mapping to an enum?
I was facing with similar problem and found simple answer.
You can do something like:
#Column(name = "my_type")
#ColumnTransformer(read = "UPPER(my_type)", write = "LOWER(?)")
#Enumerated(EnumType.STRING)
private MyType type;
(you don't need for "write" in #ColumnTransformer - for me it's for back compatibility, because my rows only in lower case. Without write Hibernate will write enum in same case, as in code in enum constant)
You can map an enum as an ORDINAL or a STRING with hibernate annotations, for example:
#Enumerated(EnumType.ORDINAL)
private State state;
The ordinal mapping puts the ordinal position of the enum in the database. If you change the order of the enum values in your code this will conflict with existing database state. The string mapping puts the upper case name of the enum in the database. If you rename an enum value, you get the same problem.
If you want to define a custom mapping (like your code above) you can create an implementation of org.hibernate.usertype.UserType which explicitly maps the enum.
First I suggest some changes to your enum to make what follows possible:
public enum State {
ACTIVE("active"), INACTIVE("inactive");
private String stateName;
private State(String stateName) {
this.stateName = stateName;
}
public State forStateName(String stateName) {
for(State state : State.values()) {
if (state.stateName().equals(stateName)) {
return state;
}
}
throw new IllegalArgumentException("Unknown state name " + stateName);
}
public String stateName() {
return stateName;
}
}
And here is a simple (!) implementation of UserType:
public class StateUserType implements UserType {
private static final int[] SQL_TYPES = {Types.VARCHAR};
public int[] sqlTypes() {
return SQL_TYPES;
}
public Class returnedClass() {
return State.class;
}
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
String stateName = resultSet.getString(names[0]);
State result = null;
if (!resultSet.wasNull()) {
result = State.forStateName(stateName);
}
return result;
}
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException {
if (null == value) {
preparedStatement.setNull(index, Types.VARCHAR);
} else {
preparedStatement.setString(index, ((State)value).stateName());
}
}
public Object deepCopy(Object value) throws HibernateException{
return value;
}
public boolean isMutable() {
return false;
}
public Object assemble(Serializable cached, Object owner) throws HibernateException
return cached;
}
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable)value;
}
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y) {
return true;
}
if (null == x || null == y) {
return false;
}
return x.equals(y);
}
}
Then the mapping would become:
#Type(type="foo.bar.StateUserType")
private State state;
For another example of how to implement UserType, see: http://www.gabiaxel.com/2011/01/better-enum-mapping-with-hibernate.html

com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(Object o) doesn't write a field into JSON string

I need to convert object of Student to JSON string. Object of StudentId is an attribute of Student. When I write Student to string using com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(Student s), I see all other attributes are converted to JSON string except StudentId. What do I missing StudentId class? When I debug, I do see studentId field before calling writeValueAsString(student), but somehow isn't written into JSON string.
public class StudentId extends AbstractLongId{
public StudentId(final Long id) {
super(id);
}
public StudentId(final String id) {
super(id);
}
}
public class Student {
private DateTime created;
private StudentId studentId;
private String name
}
public abstract class AbstractLongId extends AbstractId<Long> {
public AbstractLongId(final Long value) {
super(value);
}
public AbstractLongId(final String value) {
super(value);
}
#Override
protected Long fromString(final String value) {
try {
return new Long(value);
}
catch (NumberFormatException e) {
throw new IllegalArgumentException("Note valid input");
}
}
}
public abstract class AbstractId<T> extends Wrapper<T> implements Id<T> {
public AbstractId(final T value) {
super(value);
}
public AbstractId(final String value) {
super(value);
}
}
public abstract class Wrapper<T> {
private final T value;
public Wrapper(final T value) {
this.value = value;
}
public Wrapper(final String value) {
T typedValue = fromString(value);
this.value = typedValue;
}
protected abstract T fromString(final String value);
public T getValue() {
return value;
}
#Override
public String toString() {
return value.toString();
}
public boolean equalsString(final String other) {
if (other == null) {
return false;
}
return value.toString().equals(other);
}
#Override
#SuppressWarnings("unchecked")
public boolean equals(final Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Wrapper)) {
return false;
}
Wrapper<T> otherId = (Wrapper<T>) other;
return value.equals(otherId.getValue());
}
#Override
public int hashCode() {
return value.hashCode();
}
}

Hibernate doesn't recognize my enum type declared with #Type annotation

I have the following entity:
#Entity
#Table(name="filter", schema="mailing")
public class FilterItemValue {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Type(
type = "my.package.generic.enum.GenericEnumUserType",
parameters = {
#Parameter(
name = "enumClass",
value = "ua.com.winforce.casino.email.db.entity.FilterItem"),
#Parameter(
name = "identifierMethod",
value = "getValue"),
#Parameter(
name = "valueOfMethod",
value = "getByValue")
}
)
#Column(name = "filter_item_id")
private FilterItem filterItemId;
//Other fields and properties
}
Where GenericEnumUserType is:
public class GenericEnumUserType implements UserType, ParameterizedType {
private static final String DEFAULT_IDENTIFIER_METHOD_NAME = "name";
private static final String DEFAULT_VALUE_OF_METHOD_NAME = "valueOf";
private Class<? extends Enum> enumClass;
private Class<?> identifierType;
private Method identifierMethod;
private Method valueOfMethod;
private NullableType type;
private int[] sqlTypes;
public void setParameterValues(Properties parameters) {
String enumClassName = parameters.getProperty("enumClass");
try {
enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
} catch (ClassNotFoundException cfne) {
throw new HibernateException("Enum class not found", cfne);
}
String identifierMethodName = parameters.getProperty("identifierMethod", DEFAULT_IDENTIFIER_METHOD_NAME);
try {
identifierMethod = enumClass.getMethod(identifierMethodName, new Class[0]);
identifierType = identifierMethod.getReturnType();
} catch (Exception e) {
throw new HibernateException("Failed to obtain identifier method", e);
}
type = (NullableType) TypeFactory.basic(identifierType.getName());
if (type == null)
throw new HibernateException("Unsupported identifier type " + identifierType.getName());
sqlTypes = new int[] { type.sqlType() };
String valueOfMethodName = parameters.getProperty("valueOfMethod", DEFAULT_VALUE_OF_METHOD_NAME);
try {
valueOfMethod = enumClass.getMethod(valueOfMethodName, new Class[] { identifierType });
} catch (Exception e) {
throw new HibernateException("Failed to obtain valueOf method", e);
}
}
public Class returnedClass() {
return enumClass;
}
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
Object identifier = type.get(rs, names[0]);
if (identifier == null) {
return null;
}
try {
return valueOfMethod.invoke(enumClass, new Object[] { identifier });
} catch (Exception e) {
throw new HibernateException("Exception while invoking valueOf method '" + valueOfMethod.getName() + "' of " +
"enumeration class '" + enumClass + "'", e);
}
}
public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
try {
if (value == null) {
st.setNull(index, type.sqlType());
} else {
Object identifier = identifierMethod.invoke(value, new Object[0]);
type.set(st, identifier, index);
}
} catch (Exception e) {
throw new HibernateException("Exception while invoking identifierMethod '" + identifierMethod.getName() + "' of " +
"enumeration class '" + enumClass + "'", e);
}
}
public int[] sqlTypes() {
return sqlTypes;
}
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
public Object deepCopy(Object value) throws HibernateException {
return value;
}
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
public boolean equals(Object x, Object y) throws HibernateException {
return x == y;
}
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
public boolean isMutable() {
return false;
}
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}
and the enum itself:
public enum FilterItem implements StringRepresentable{
AMOUNT(1) {
#Override
public List<RuleItem> getItemRules() {
List<RuleItem> result = new ArrayList<RuleItem>();
result.add(RuleItem.EQUAL);
return result;
}
#Override
public FilterItemType getFilterItemType() {
return FilterItemType.FIELD;
}
#Override
public String getStringRepresentation() {
return getFilterItemStringRepresentation("dynamicFilterItemName.amount");
}
#Override
public MapperType getMapperType() {
return null;
}
#Override
public RestrictorType getRestrictorType() {
return RestrictorType.RANDOM_AMOUNT;
}
#Override
public JunctionBuilderParams getJunctionBuilderParams() {
return null;
}
},
//Other enums
public static FilterItem getByValue(int val) {
FilterItem[] values = FilterItem.values();
for (FilterItem value : values) {
if (val == value.getValue()) {
return value;
}
}
throw new IllegalArgumentException("Illegal value: " + val);
}
public abstract String getStringRepresentation();
public abstract List<RuleItem> getItemRules();
public abstract FilterItemType getFilterItemType();
public abstract MapperType getMapperType();
public abstract RestrictorType getRestrictorType();
public abstract JunctionBuilderParams getJunctionBuilderParams();
}
So, when I debug my application the method
public static Type heuristicType(String typeName, Properties parameters)
throws MappingException
at org.hibernate.type.TypeFactory
first executes this instruction Type type = TypeFactory.basic( typeName ); where typeName = "GenericEnumUserType". Therefore TypeFactory.basic(typename) returns null and I end up with the exception:
org.hibernate.MappingException: Could not determine type for: my.package.generic.enum.GenericEnumUserType, for columns: [org.hibernate.mapping.Column(filter_item_id)]
org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:266)
org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:253)
How to fix that, what's wrong?
Maybe it was caused by the abstract methods I defined in the FilterItem enum?

Categories