java beans: difference between persistent field and persistent property? - java

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.

Related

Why do we need getters when we create ORM class?

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.

mapping superclasses and subclasses with hibernate (JPA)

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 {
...
}

Is it possible to have immutable fields in Hibernate/JPA?

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;
}
}

is it possible to make all fields of an object #Transient by default

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.

Why can't entity class in JPA be final?

Why can't an entity class in JPA be final or have a final methods? Citing from here -
An entity class must follow these requirements:
...
The class must not be declared final. No methods or persistent instance variables must be declared final.
What is the reason? Is JPA subclassing the entity classes and redefining the methods?
By definition, an entity is a class that can be persisted to a database, so having a final field would make no sense in the context of something that will end up being a record in your database. The requirement of no final class and no final methods has to do with the way in which JPA implementations actually deal with persisting instances of your entities classes.
It is common for implementations to subclass your class at runtime and/or add byte code dynamically to your classes, in order to detect when a change to an entity object has occurred. If your class is declared as final, then that would not be possible.
There is of course a lot more reasons than just those, here is an article that gives more information of how ORM in general work behind the covers, that might help you better understand the other requirements for JPA entities.
Because persistence providers make proxies of objects. These proxies are creating runtime subclasses of the entities/classes and also might be adding some flags to identify whether there is a change in the data. so that is why your class should not be final to have the ability to change it.

Categories