Is there a way to tell JPA / EclipseLink to ignore enums it encounters in the database that aren't defined in the java enum?
Instead of getting this exception: No conversion value provided for the value...
There doesn't seem to be a way to add an enum to the DB, promote a new version of the code, while keeping another old instance of the code running on the same database.
EclipseLink uses an EnumTypeConverter to convert Enums, which is a subclass of ObjectTypeConverter.
If you use an #ObjectTypeConverter directly, you can set a defaultObjectValue to default values from the database that are not mapped. You could also use your own Converter, or set the defaultValue in the EnumTypeConverter through a DescriptorCustomizer.
Related
Currently i am migrating my legacy application from Oracle to Postgres.
Within my POJOs i am having issues with following new datatypes.
Datatype in Oracle
New Datatype in Postgres
Data Type in Spring Boot (Hibernate Entity)
NUMBER(X,0)
NUMERIC(X,0)
String
SMALLINT
NUMERIC(1,0)
boolean
How can i map this within my Hibernate Entity correctly?
Currently i am getting always Type Exceptions because of character does not match numeric etc.
For the boolean is somehow fixed it by adding #Type(type="org.hibernate.type.NumericBooleanType)
but there i have also to change the Java Type from boolean to Boolean which i would like to avoid
My current research should i need to write an own UserType for it, but somehow i am bit confused because i don't think Numeric to String / boolean is such a rare case so that nobody included already a Logic / UserType within Hibernate.
I'm using Hibernate, JPA and Spring Boot.
I would like to persist a custom Object of type "Version". "Version" is an Object with complex processing but it corresponds in the table to a simple VARCHAR field. I'm able to construct Version from String and construct String from Version object.
class MyEntity {
#Column("version_sw")
private Version version; <-- I would like to persist version as a String
}
I'm looking at different way to create hibernate type :
UserType : Seems overkill for me because my object map to only one Column in database.
BasicType (with AbstractTypeDescriptor) : Seems good but not sure if it's the right way to do that
CompositeUserType : Seems not good for my needs
Is there a missing and simple way in order to do that ?
Thanks !!
If I understend you just need to convert you object to strings and save on data base, to do that you can use JPA attribute converter, so you can convert your complex object to string, some kind of json for exemple and save it on table. And to use on your system you must convert the string to one object.
Try this: https://thoughts-on-java.org/jpa-21-how-to-implement-type-converter/
Currently I have to add #Enumerated(EnumType.STRING) to all fields that use enums, and very often I forget to do it, and then the default kicks in (EnumType.ORDINAL).
Is it possible to configure JPA to map all enums to String? (To make the default EnumType.STRING ?)
Unfortunately not.
But think twice when using enums. I wrote an article about the issues:
https://martinelli.ch/should-you-use-enums-with-jpa/
I'm working on creating a JPA 2.0 Annotation compliancy kit for my internship.
Right now, I'm wondering when a #MapKeyTemporal annotation is required and when it's optional...
I know that when you define the column of the map key using #MapKeyColumn, the type the key should be mapped to can be derived by looking at the type of the column (and otherwise the type in the columndefinition). Thus, in this case, no #MapKeyTemporal annotation is necessary.
When you attach the #MapKeyTemporal annotation, the column name is defaulted to ATTRIBUTE + "_KEY".
When you don't annotate #MapKeyColumn and #MapKeyTemporal, the column name is defaulted to ATTRIBUTE + "_KEY", but to what type does the key default? Or are you supposed to get an error?
I looked for a similar situation and found #MapKeyEnumerated.
It's the same because it's related to #MapKeyColumn and it's a value that can be mapped to multiple datatypes (java.sql.Date/java.sql.Time/java.sql.Timestamp for #MapKeyTemporal, and EnumeratedType.ORDINAL/EnumeratedType.STRING for #MapKeyEnumerated).
I found one difference:
#MapKeyEnumerated has a default. This default is EnumeratedType.ORDINAL.
My question:
When using a map that has a map key whose basic type is a temporal type, what's the default TemporalType (according to JPA 2.0) to which the map key is converted for persistence?
Answer seems to be, that there is no default type when java.util.Date or java.util.Calendar is used as key of the map. Specification itself (I do consider javadocs delivered with specification as part of specification) is very strict about usage of MapKeyTemporal. Javadoc for MapKeyTemporal claims:
This annotation must be specified for persistent map keys of type Date
and Calendar.
I think with such a strictness they forgot case that you present, having type information from attribute referenced by MapKey. It does not make too much sense to specify type in the case of MapKey, because type is already specified in the entity that is value of the map. Also allowing possibility to have different temporal type for key of the map for corresponding field in the entity is not desirable.
If MapKeyTemporal is not specified and if there is no other way to figure out type of the key, EclipseLink (reference implementation, though it is not always following specification) produces following exception:
org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [map] from the entity class [class X]
does not specify a temporal type. A temporal type must be specified for persistent
fields or properties of type java.util.Date and java.util.Calendar.
at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:126)
Basically, you are not asking if there is a default type for MapKeyTemporal but if implementations of JPA 2.0 or the spec are using a default value for Temporal Types.
Which implies that there is a more important type in a database between Date and Timestamp, that is probably not the case.
Also if you have a Calendar, the implementation probably calls getTime() and then constructs a new Sql type from there, how does it decide on the implementation ?
Reminder :
The first reason for the existence of temporal is simply because a key with the class java.util.Date can be either of the three time types in Java (Time, Timestamp and sql.Date), while this doesn't matter in Java, it does in a database where these are distinct types.
If I do not specify a temporal type, nothing stops me from having different sql types for the same Entity, breaking at runtime.
I have a field aliases of type java.util.Set in one Entity. This Set doesn't denote any relationship to an Entity.
How can I store this aliases field through JPA?
How this field get stored in database? I think that for the database, this field is a multi-valued attribute.
How can I store this aliases field through JPA?
JPA 1.0 doesn't support collections of basic types so you'll have to either:
Introduce an entity and map it as a #OneToMany ~or~
Get your Set stored in a BLOB (as a Serializable) ~or~
Mark it #Transient and use another getter/setter to store it using a custom string representation (using a seperator) ~or~
Use an extension of your JPA provider supporting collection of basic types (e.g. Hibernate has the #CollectionOfElements annotation).
Solution #1 would be the cleanest portable solution. Solution #2 can lead to some troubles on upgrades. Solution #3 is a ugly workaround for #2. Solution #4 is clean but non portable.
In JPA 2.0, there is the #ElementCollection annotation for this use case (this is of course the ideal solution).
How this field get stored in database
Depending on the chosen implementation, it may be in a BLOB, in a VARCHAR, in another table.