How to persist java.util.Set through JPA? - java

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.

Related

Using Sequence in non Id field In jpa and Sql Server

My JPA Entity contiens a non id field named counter, the value of this field is getted from Sql server sequence.
How can i represente this requirement in my JPA mapping of the entity ?
I note that i can't add/modify the dabatabase objects ( triger/ function / procedure ), the solution must be bassed on JPA
Thanks !
JPA does not define #GeneratedValue on non-ID fields. However some JPA implementations (e.g the one I use DataNucleus JPA) do allow it, hence if using one of those implementations then you could just annotate the field as SEQUENCE.

JPA / EclipseLink and backwards compatible enum mapping

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.

SortedMap Key Persistance in Hibernate

I'm hoping someone can help me with my hibernate issue as I've been banging my head against Google for around an hour without result.
So the issue is that I have a SortedMap in a class, using Integer as the Key (and its natural built-in compareTo method) and another class as the value type. I'm using the key to keep the user-defined order of the value type and trying to get Hibernate to persist this.
For whatever reason, Hibernate has defaulted to disregarding the key I have inputted and instead using the value type's primary key as the key instead. When I load my Map back out of the database all of my keys have been changed in this way.
Definition of the Map is shown below (I'm using annotation-style Hibernate);
#ManyToMany(cascade = CascadeType.ALL)
#MapKey
#Sort(type = SortType.NATURAL)
private SortedMap<Integer, Column> columnOrder;
I can't use the Column type to store the order itself as the Column may be used in many instances of the containing type, with a different key value each time. Any guidance would be most appreciated.
So I found the answer after discovering this StackOverflow question with a similar issue: Sorted map of Java primitives using JPA2 and Hibernate?
By changing the #MapKey annotation to the #MapKeyColumn annotation, I was able to give Hibernate the instruction to persist the key in the column name I specified, as below;
#ManyToMany(cascade = CascadeType.ALL)
#MapKeyColumn(name = "hierarchyOrdering")
#Sort(type = SortType.NATURAL)
private SortedMap<Integer, Column> columnOrder;
Thanks for the help.
From the javadoc of javax.persistence.OrderColumn:
Specifies a column that is used to maintain the persistent order of a list. The persistence provider is responsible for maintaining the order upon retrieval and in the database. The persistence provider is responsible for updating the ordering upon flushing to the database to reflect any insertion, deletion, or reordering affecting the list.
So it is possible to use a list for that.
The JPA 2.0 spec states in section 2.2 Persistent Fields and Properties:
Collection-valued persistent fields and properties must be defined in terms of one of the following collection-
valued interfaces regardless of whether the entity class otherwise adheres to the JavaBeans
method conventions noted above and whether field or property access is used: java.util.Collection,
java.util.Set, java.util.List[3], java.util.Map. The collection implementation
type may be used by the application to initialize fields or properties before the entity is made
persistent. Once the entity becomes managed (or detached), subsequent access must be through the
interface type.
So it seems as if a SortedMap is not supported by JPA.

How to get selection with ManyToMany relationship in the Play framework [duplicate]

I have a simple jpa entity 'ApplicationForm' with a one to many list in it:
#OneToMany(cascade=CascadeType.REMOVE, mappedBy="textQuestion")
private List<Dictionary> questions;
The variable Dictionary contained in ApplicationForm is just another plain entity with just the text of the question.
The corresponding database table mapped by Dictionary is:
'locale' 'text' 'formId'
en my question 123
it mia domanda 123
I was wondering if it's possible with jpa or hibernate, to build a query for retrieving an ApplicationForm entity with a Dictionary for a specific locale, for example 'it' only.
That would be easy enough to do with standard sql, but I cannot translate in hql.
If not possible, could you suggest an alternative way ? I have tried to manually iterate the Dictionary questions list and remove the not required locale, but is not really elegant, and also I got a jpa/hibernate error.
I hope I made myself clear, and code supplied is enough.
thanks
I was wondering if it's possible with jpa or hibernate, to build a query for retrieving an ApplicationForm entity with a Dictionary for a specific locale, for example 'it' only.
Not with standard JPA. But Hibernate allows to apply arbitrary filters to a collection load during a given session. From the Hibernate Annotations Reference Guide:
2.4.8. Filters
Hibernate has the ability to apply
arbitrary filters on top of your data.
Those filters are applied at runtime
on a given session. First, you need to
define them.
#org.hibernate.annotations.FilterDef
or #FilterDefs define filter
definition(s) used by filter(s) using
the same name. A filter definition has
a name() and an array of
parameters(). A parameter will allow
you to adjust the behavior of the
filter at runtime. Each parameter is
defined by a #ParamDef which has a
name and a type. You can also define a
defaultCondition() parameter for a
given #FilterDef to set the default
condition to use when none are defined
in each individual #Filter. A
#FilterDef(s) can be defined at the
class or package level.
We now need to define the SQL filter
clause applied to either the entity
load or the collection load. #Filter
is used and placed either on the
entity or the collection element
#Entity
#FilterDef(name="minLength", parameters=#ParamDef( name="minLength", type="integer" ) )
#Filters( {
#Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length"),
#Filter(name="minLength", condition=":minLength <= length")
} )
public class Forest { ... }
When the collection use an association
table as a relational representation,
you might want to apply the filter
condition to the association table
itself or to the target entity table.
To apply the constraint on the target
entity, use the regular #Filter
annotation. However, if you wan to
target the association table, use the
#FilterJoinTable annotation.
#OneToMany
#JoinTable
//filter on the target entity table
#Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length")
//filter on the association table
#FilterJoinTable(name="security", condition=":userlevel >= requredLevel")
public Set<Forest> getForests() { ... }
See also
Chapter 17. Filtering data In the Hibernate Core Reference Documentation.
Hibernate3 Filters

Why doesn't the Hibernate generate a DDL with column for serialVersionUID?

I get this DDL (postgres target) when I add the goal hbm2ddl using the Maven plugin hibernate3-maven-plugin:
create table listing (
id varchar(36) not null,
hash_code int4 not null,
version int4,
name varchar(100),
primary key (id)
);
I defined all the columns shown.
All examples of using that I have seen on the web of:
private static final long serialVersionUID = -8402611044513083864L;
never have a #Column annotation. My DDL does not have a column for it. Does anybody else's?
So how does the deserialization code in Java know what version of a class was serialized and stored vs the one that it is being deserialized into?
Serial version UID is used when object is serialized / deserialized.
If you annotate your object as an JPA Entity you're not using a serialization but just transforming your object to another representation - as a row in the database table.
When you fetch the row from the database, this data is used to create a new instance of object with properly set state.
Serialization, on the other hand, is used if you want to construct a binary representation of your object and then recreate the object instance using deserialization process.
Note that you can use serialization with JPA i.e. if you want to persist a field (within your JPA entity) which is neither a basic type, embeddable nor other entity but just a plain Java class which implements Serializable marker interface.
However, in this case only this given field in your entity is using serialization/deserialization to put binary data into database column. Still - the serial version UID is not stored anywhere in the database.
For more information about persistent fields (which are persisted and which are not) you can take a look at 2.2 Persistent Fields and Properties chapter in JPA 2.0 FR specification.
static values are never serialized, and JPA does not use java serialization.

Categories

Resources