the difference between anotating a field and its getter method JPA - jpa

i'm trying to figure wether there's a difference betweeen anotating (let's take #id as an example) a getter method and the concerned field directly , in case i annotate the field , does JPA use some kind of reflection to invok the corresponding getter ?
because in my case i'm trying to obfuscate my entity classes , so i'm looking for a way to keep the business logic since the getters will be renamed into something like aaa() .

Here's what the section 2.3.1 of the JPA2 specification says:
By default, a single access type (field or property access) applies to
an entity hierarchy. The default access type of an entity hierarchy is
determined by the placement of mapping annotations on the attributes
of the entity classes and mapped superclasses of the entity hierarchy
that do not explicitly specify an access type. An access type is
explicitly specified by means of the Access annotation[6], as
described in section 2.3.2. When annotations are used to define a
default access type, the placement of the mapping annotations on
either the persistent fields or persistent properties of the entity
class specifies the access type as being either field- or
property-based access respectively.
When field-based access is used, the object/relational mapping annotations for the entity class annotate the instance variables, and
the persistence provider runtime accesses instance variables directly.
All non-transient instance variables that are not annotated with the
Transient annotation are persistent.
When property-based access is used, the object/relational mapping annotations for the entity class annotate the getter property
accessors[7], and the persistence provider runtime accesses persistent
state via the property accessor methods. All properties not annotated
with the Transient annotation are persistent.
Mapping annotations must not be applied to fields or properties that are transient or Transient.
All such classes in the entity hierarchy whose access type is
defaulted in this way must be consistent in their placement of
annotations on either fields or properties, such that a single,
consistent default access type applies within the hierarchy. Any
embeddable classes used by such classes will have the same access type
as the default access type of the hierarchy unless the Access
annotation is specified as defined below. It is an error if a default
access type cannot be determined and an access type is not explicitly
specified by means of annotations or the XML descriptor. The behavior
of applications that mix the placement of annotations on fields and
properties within an entity hierarchy without explicitly specifying
the Access annotation is undefined.
So, if you want to avoid problems with the obfuscation, then annotate the fields and not the getters, consistently, or use the #Access annotation to force field access type.

JPA allows for two types of access to the data of a persistent class. Field access which means that it maps the instance variables (fields) to columns in the database and Property access which means that is uses the getters to determine the property names that will be mapped to the db. What access type it will be used is decided by where you put the #Id annotation (on the id field or the getId() method).

Related

JPA bean validation use field or property access?

JPA bean validation use field or property access? It should use the same access type for both JPA and validation. How to tell validation provider which one should be used?
public class Foo {
#NotNull
private String name;
#Size(20)
public String getName() {
}
}
Bean Validation constraints can be on both the field and the property getter. The spec however recommends using only one access strategy, and when using JPA use the same access strategy used for persistence.
Here is the relevant part of the Bean Validation spec (see section 5.1.2):
Constraint declarations can be applied on both fields and properties
for the same object type. The same constraint should however not be
duplicated between a field and its associated property (the constraint
validation would be applied twice). It is recommended for objects
holding constraint declarations to adhere to a single state access
strategy (either annotated fields or properties).
NOTE
Java Persistence and Bean Validation For maximum portability, persistent
properties hosting Bean Validation constraints should use the same
access strategy used in Java Persistence. In other words, place your
Bean Validation constraint annotations on the same element (field or
getter) as your Java Persistence annotations.
When a field is
annotated with a constraint declaration, field access strategy is used
to access the state validated by such constraint.
When a property is
annotated with a constraint declaration, property access strategy is
used to access the state validated by such constraint.

sometimes persistence is still allowed to loads data as an eagerly?

I read this in the EJB/JPA Book:
"Even if you mark the property as LAZY for a #Basic type, the persistence provider is still allowed to load the property eagerly. This is due to the fact that this feature requires class-level instrumentation. It should also be noted that lazy loading is neither really useful nor a significant performance optimization. It is best practice to eagerly load basic properties."
QUESTION 1)
If I set property as an LAZY, why e persistence provider is still allowed to load the property eagerly? when this happens? and why? is this for primitives only?
QUESTION 2)
"The #Basic annotation is the simplest form of mapping for a persistent property. This is the default mapping type for properties which are primitives, primitive wrapper types"
If I use does not use primitive or wrapper (for instance I use my class object), will he persistence provider is still allowed to load the property eagerly?
QUESTION 3)
"You do not need to tell your persistence manager explicitly that you're mapping a basic property because it can usually figure out how to map it to JDBC using the property's type."
As I understand this happens when I use primitives or wrappers, don't I? And how does it figure out how to map? Is there any obvious rule?
QUESTION 1)If I set property as an LAZY, why e persistence provider is
still allowed to load the property eagerly? when this happens? and
why? is this for primitives only?
Because of performance issues: the JPA provider has the right (according to the JPA spec) to decide that it is better to fetch the field eagerly. This is valid also for wrapper fields & Strings. It is not specified when this happens, which means that can happen when the JPA provider considers it needed.
QUESTION 2)"The #Basic annotation is the simplest form of mapping for
a persistent property. This is the default mapping type for properties
which are primitives, primitive wrapper types"
If I use does not use primitive or wrapper (for instance I use my
class object), will he persistence provider is still allowed to load
the property eagerly?
Actually yes, also for relationships you have the same rule, although almost always the JPA provider will consider your hint. Of course: when you have a field of type YouClass, you are not allowed to annotate it with #Basic and must use #ManyToOne-like annotations. You will read further about them.
QUESTION 3) "You do not need to tell your persistence manager
explicitly that you're mapping a basic property because it can usually
figure out how to map it to JDBC using the property's type."
As I understand this happens when I use primitives or wrappers, don't
I? And how does it figure out how to map? Is there any obvious rule?
That happens will all types listed in the documentation of the #Basic annotation, not only those that you enumerated. The rule is pretty simple: String types are mapped as VARCHAR/CHAR like columns, number-fields like NUMBER (or DECIMAL) and so further.

Can I use New() method in Entity Framework partial classes

I have extended Entity Framework autogenerated classes with custom partial classes and added several new properties and business login into it. I need to populate those properties any time objects are either materialized from the database or created from scratch without a database contact.
Can I use or is it advised to use the New() method inside the class for that? (I know there is an event ObjectContext.ObjectMaterialized as well).
As an example, in my partial class i have a property
Public Property Employees As List(Of Employee)
and I want to instantiate that list somewhere (where?).
You could just write a default constructor for those entities where you set default property values. Notice Entity Framework doesn't create constructors for you, so they can easily be added in partial classes.

Does Entity Framework support the null object pattern?

What are my options for using the null object pattern with Entity Framework? All my business objects have a static 'Empty' null object (similar to Guid.Empty, String.Empty and others), and these are assigned to properties of related objects when a null value is selected from the database.
NHibernate supports this pattern through field access with handler code in corresponding properties (an example). How does Entity Framework support this? What about empty lists for one-to-many relations?
The article just uses mapped field and unmapped property - you can use similar approach with two properties in EF. The approach will come with some complications because specifying eager loading is allowed only on mapped properties and lazy loading has also some requirements (dynamic proxy must override the mapped property).
Also whole meaning of null object may be little bit complicated because null with EF means either unassigned or not loaded (if you turn off lazy loading).

Maaping result of stored procedure to constructor in Entity Framework

In Entity Framework I am mapping result of a stored procedure to a complex type of my class. I want to assign stored procedure's results directly to the constructor of the class rather than a complex type. Is that possible?
It is not possible. EF doesn't support constructor with parameters. You must expose default constructor and accessible setter for each property.