I am trying to persist objects in a database using hibernate JPA.
The objects already have a type hierarchy, and I'm trying to make it work with hibernate.
A CatalogPackage object has all the important properties and all the getters.
A CatalogPackageImpl (extends CatalogPackage) object has no properties, but most of the setters.
Both classes are non-abstract.
We want code to refer to CatalogPackage objects. But when initializing hibernate, it complains about the setters missing from the CatalogPackage class.
How do I suggest to hibernate that it use the subclass when building the objects?
I don't want to move all the setters to the superclass, and I don't want to use CatalogPackageImpl as the entity.
Even though I can't see the problem with defining the setter methods in your CatalogPackage since they can be marked private to avoid using them from external world.
Since you didn't paste your entities configuration and that you say Hibernate is complaining about the setter methods I can conclude you are using your getters to describe your entity mapping, right?
In such a case Hibernate will always still complaining because it assumes anything mapped to the database should be done in both directions, if it can read from the datastorage so it should be allowed to write in there.
SO you have either of below solutions:
Add the setters modifiers.
Move the mapping from getter methods to fields and set the acces type to field on top of your entity:
#Access(AccessType.Field)
class CatalogPackage {
...
}
Related
I am implementing JPA and using Hibernate to implement ORM. I have created a class to represent a table in my database and private properties to represent the columns of the table with their getters and setters. I successfully fetched and added data to the table with and without the getters.
My question is:
Why do we need getters in this case if the data can be managed without getters?
Getters/Setters are from the Java Beans convention: https://en.wikipedia.org/wiki/JavaBeans
You don't have to use that!
According to the JPA specification fields in an Entity shouldn't be public.
The instance variables of a class must be private, protected, or
package visibility independent of whether field access or property
access is used. When property access is used, the property accessor
methods must be public or protected.
But this doesn't mean that you need getters and setters if you can access the data via other methods. Btw. Hibernate allows public fields.
In our application, we need to have fields that are assignable only once.
At first we thought of encapsulating the fields and making the setters private. However, some questions arouse:
Without a public setter, is Hibernate still able to map the field from the database?
Can I strip out the setter and make the field mutable only in the entity constructor?
Finally, is there any standard JPA way to make a field immutable?
Thanks in advance.
Try
#Column(updatable = false)
And make your setter private. (Leave your getter public if you want)
I think this is the best practice.
P.S.: JPA uses field access if you annotate your fields and uses getter/setter access if you annotate your getter method.
Ad. 1: I believe JPA uses plain private fields for both read and write if annotations are placed on fields and not on getters. Recently I discovered that Hibernate as an underlying JPA provider does not even need get*() and set*() methods at all. This was truly enlightening solution since from the beginning I thought Hibernate needs accessors. So the answer is: you don't need setters as far as Hibernate is concerned.
Ad. 2: However please note that Hibernate still needs no-arg constructor, otherwise it will fail to load entities with a descriptive exception. This is also a JPA requirement.
Ad. 3: No, there isn't. Remember that your collections would also had to be immutable.
Try
#Column(updatable = false)
From javadoc:
Whether the column is included in SQL UPDATE statements generated by
the persistence provider.
In JPA 2.0 you have two ways to define what attributes should be persisted:
Access(FIELD) - the fields name are persisted,
Access(PROPERTY) - the properties name are persisted.
If no Access(-) annotation is used, the decision what access will be used depends on where you put your #Id annotation. If you put it next to your field - Access(FIELD) will be used. If you put it next to your accessor - Access(PROPERTY) will be used.
Therefore, if you use Access(FIELD) you don't have to have an appropriate JavaBeans-style accessor for particular field. You can have a private field named 'myField' and a public setter for it named 'public setBlahBlah(-)'. The JPA will persist just the 'myField'.
You can mark an entity with #Entity(mutable=false) or #Immutable annotations for the framework to make use of this fact for performance gain in caching and such. (Hibernate)
Then you can use an immutable wrapper class like this:
public class ImmutableStuff {
private final FooField barValue;
public ImmutableStuff(Stuff stuff) {
barValue = stuff.barValue;
}
public FooField getBarValue(){
return barValue;
}
}
I have a base Entity class which will be derived in more than a hundred of a subclasses.
In order to be sure that persisted fields will be the ones I want (and not the users of that base class), I want to declare this JPA entity as setting all fields as transient by default.
How is it possible ?
If you don't put #MappedSuperclass on your class you are extending from, the class properties will never by persisted.
You can provide getter methods for certain properties, and place the annotations on the properties instead of the fields. The #Id annotation determines if you want the fields or the properties. In JPA 2 you can also use the #Access annotation.
I have about 10 different entities in my J2EE application that right now share the exact same implementation. They all inherit from the same generic abstract class that has been annotated as a #MappedSuperclass, but this class contains none of the implementation I have repeated in all the concrete subclasses.
If I could, I'd put all the various fields and collections on this abstract superclass and therefore put the implementation methods there too -- all in one place instead of 10. However, due to JPA restrictions I cannot add JPA annotations to generic fields or accessors.
While I normally favor delegation to implementation inheritance anyway, due to another JPA restriction that says you can't have an embedded entity with a collection the idea of using a delegate also won't work.
When I had only 3-4 of these entities and 2-3 methods, it wasn't a big deal, but now I have about 10 -- and about 7-8 methods each...and some of the methods are getting really complex. And the "cut-copy-paste" inheritance I am using really sucks.
Any other brilliant ideas out there?
Double-check whether these "restrictions" actually hold true for your JPA provider. I've had embedded objects with collections and it has been fine (with Hibernate). And I've had a #MappedSuperclass with mapped fields.
You can try omitting the #MappedSuperclass, and make the superclass abstract and an #Entity with the proper inheritance hierarchy.
It turns out you can use either implementation inheritance or delegation as long as you are sure to use property access mode for your JPA annotations. I was using field access mode for JPA annotations and that was causing me no end of suffering because I could not annotate a generic field type.
However with property access mode I simply create my generic abstract implementation without annotating it as an entity, mappedsuperclass, embeddable, or anything. This way JPA will ignore it. Then, in the concrete subclasses, I create protected getter and setters methods as needed and put the JPA annotation on those.
Turned out to be deceptively simple.
I got the impression that if we use persistent fields, there is no need for getter methods since the entity manager references the instance variables directly. However, when I removed the getter and setter methods from an entity to have persistent fields, the values for the corresponding instance variable was not retrieved from the database!
Does that mean we must have getter and setter methods even though we have persistent fields?
If the entity class uses persistence, fields Persistence accesses the entity class instance variables directly at runtime.
While on persistence property, there is a getter and a setter method for each property.
What you said should have worked on hibernate.
A link about it
You don't mention what JPA implementation you are using. Hibernate certainly allows you to access fields directly. However, it is not the default setting, so you have to specify this behavior in the mapping files with access=field. (with annotation based configuration, I would imagine you just need to annotate the fields directly ...)
What provider is that? I'd expect it to work. Anyway, just create protected getter and setter methods as a workaround if your provider needs that.