JPA 2.0 field annotation vs method annotation - java

in JPA 2.0 which is the difference between annotating a field and annotating a method (typically a getter)?
Example with field annotation
#Entity
public class MainEntity {
#Id
private Long id
#OneToMany
private RelatedEntity relatedEntity
//getters and setters and possible other methods
...
}
Example with method annotation
#Entity
public class MainEntity {
#Id
private Long id;
private RelatedEntity relatedEntity
//getters and setters and possible other methods
#OneToMany
public RelatedEntity getRelatedEntity(){
return relatedEntity
}
//other methods etc
...
}

With JPA you can use both methods to map the columns of your table in your entity class; fields/methods access doesn't change anything from a schema generation point of view nor in terms of translated queries. Generally speaking field annotation is cleaner (frameworks like Spring encourages it), methods annotation can grant you more flexibility (like with inheriting from an abstract entity class).
Please notice that in your second example there is an error:
#Entity
public class MainEntity {
private Long id;
private RelatedEntity relatedEntity
//getters and setters and possible other methods
#Id
public Long getId() {
return id;
}
#OneToMany
public RelatedEntity getRelatedEntity(){
return relatedEntity
}
//other methods etc
...
}

From user point of view there is no difference until it is consistent, but using annotation in different places change behavior of JPA provider (hibernate, EclipseLink, etc.).
Place where annotation were set gives JPA provider information about which access type you what to use. If you mix that setting annotations in both places then provider picks one and ignores rest. In example in your second listing hibernate will ignore #Id because you have #OneToMany on method and that means you prefer to use AccessType.PROPERTY.
Of course sometimes we don't want to use property access, because we have some extra methods that provides some logic and match to naming convention. Then we should use AccessType.FIELD.
In project you should use consistent style. Mixed style is valid, but you need to define #Access for almost all elements in your POJO.

Related

when is a #Column annotation required for persistent properties of JPA classes?

In my JPA model I typically annotate each persistent class with #Entity and each persistent property with an appropriate annotation e.g. #Id, #Column, #ManyToOne, etc. A typical example is
#Entity
#Table(name = "files")
public class StoredFile {
#Id
#Type(type = "uuid-char")
private UUID id;
#Column(name = "file_name")
private String fileName;
// getters and setters omitted
}
I was looking at this example entity class and noticed that only the id field has a JPA annotation, i.e. there are no annotations specified for name or price.
Under what circumstances will a property of an #Entity be persisted if there are no annotations on the field/getter/setter?
You don't need to specify #Column annotation to persist a bean property.
#Column has to be used to specify a name of a table column. So if a naming strategy is used, you don't need to use #Column.
My advice is to always use #Column even if you don't need to specify a name.
#Column
private String fileName;
Also never mix fields and getters annotations.
Everything is primary for Hibernate.

Java ORM vs multiple entities

I have a class Health Check - as part of the class I record how many parasites are seen (enum NONE, SOME, MANY) and also the location of the parasites (enum HEAD, FEET, BODY).
Two ways this could be done:
METHOD 1
Health Check
#Entity
public class HealthCheck {
#Id
#GeneratedValue(strategy = AUTO)
private Long id;
private Parasite parasite;
Parasite
public class Parasite {
private BodyLocation bodyLocation;
private Coverage coverage;
}
Or I could have:
METHOD 2
#Entity
public class HealthCheck {
#Id
#GeneratedValue(strategy = AUTO)
private Long id;
private ParasiteNumber parasiteNumber;
private ParasiteLocation parasiteLocation;
Would method 1 require #Entity on parasite class and a entry in the table for each Health Check and a #OneToOne annotation?
Note Parasite class is not used anywhere else. Its only a part of a Health Check.
Which way is correct?
Generally speaking, yes. In ORM (aka JPA or Hibernate), you are building a graph of objects that represent things in your database. Anything that one #Entity touches is also an #Entity because it's a graph.
Whether it's a #OneToOne or a #ManyToOne, etc, depends on the nature of your data model. But, keep in mind, those connections can also be #Lazy, so they are not loaded until they are needed.
Because of #Lazy, method 2 might be preferred, idk. I assume ParasiteLocation and ParasiteNumber is some sort of join-table. If that's the case, you could load a HealthCheck with its PL and PN, but those objects could be Lazy to Parasite.
I don't think there is a one-size-fits-all answer to your question. It very much depends. But good news, ORM is flexible to cover any/all scenario you might have.
If Parasite is only used in HealthCheck class,which can be seen as an association.
Association means that the existence of child class is dependent on the existence of the parent so it has no independent lifecycle ,thus you can either declare the attributes directly in HealthCheck as you did in your second example ,or you can declare them in Parasite class and then make it Embeddable inside the HealthCheck class,e.g:
/*To embed a class inside in Entity you must declare it Embeddable via the JPA
annotation #Embeddable */
#Embeddable
public class Parasite {
#Column(name="body_location")
private BodyLocation bodyLocation;
#Column(name="coverage")
private Coverage coverage;
}
#Entity
public class HealthCheck {
#Id
#GeneratedValue(strategy = AUTO)
private Long id;
#Embedded
private Parasite parasite;
}
Here your HealthCheck db table will have the attributes specified in the Parasite class,and note that Parasite table won't be created since it is Embedded and not an Entity (#Entity).
Hope this helps!

JPA-annotated POJOs are not mapped correctly when #Column is not used for all members

I have a custom POJO on which I am mapping the database records using JOOQ .fetchInto(TestClassDto.class). Most of the fields in my POJO are exactly similar to a database table's columns. However, there are a few that are different, therefore, I added java persistence and used #Column to explicitly map such columns on my POJO as described here.
Unfortunately, this is not working if I use #Column on a few specific fields. Only the fields that are annotated with #Column are mapped and the rest are ignored and set Null even though they are similar to the table column name and should be mapped implicitly.
Could you give me a hint if I am missing anything?
Sample POJO:
#Getter
#Setter
public class TestClassDto {
#Column(name = "field_AB_XYZ") // explicit mapping is required, thus need #Column
private Long myfieldAB;
/* Here, mapping could be implicitly done without using #Column because
** database column name and POJO property is same but it stays empty if I
** ignore #Column */
#Column(name = "hello_world")
private Long helloWorld;
}
Lastly, If I completely remove #Column from POJO's properties, helloWorld property is filled (implicitly) but myfieldAb remains NULL (because mapping is not found as expected).
Below is sample query:
dslContext.select()
.from(SOMETHING)
.where(SOMETHING.NAME.eq("Something"))
.fetchInto(TestClassDto.class)
As of jOOQ 3.15, you either have to annotate
all of your attributes...
none of your attributes...
... with the #Column annotation. There's a pending feature request to mimick JPA more closely and make the #Column annotation optional for some attributes: https://github.com/jOOQ/jOOQ/issues/4586.
In the meantime, instead of using those JPA annotations, you could add auxiliary getters/setters for your column:
public void setFieldAbXyz(Long v) {
this.myfieldAB = v;
}
public Long getFieldAbXyz() {
return myfieldAB;
}

What is the difference between adding JPA annotations to fields vs getters? [duplicate]

This question already has answers here:
Hibernate Annotations - Which is better, field or property access?
(25 answers)
Hibernate/JPA - annotating bean methods vs fields [duplicate]
(5 answers)
Closed 5 years ago.
I am new to Spring Boot and JPA in general. I've seen examples of adding JPA annotations on field declarations such as this:
#Entity
public class Fizz {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// other fields
public Fizz(Long id) {
super();
setId(id);
}
// setter defined here
public Long getId() {
return this.id;
}
}
...as well as examples putting the same annotations on the getters like this:
#Entity
public class Fizz {
private Long id;
// other fields
public Fizz(Long id) {
super();
setId(id);
}
// setter defined here
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return this.id;
}
}
I'm wondering if they are semantically equivalent or if there are different use cases where you'd choose one over the other. I ask because I'm actually writing my Spring Boot/JPA app in Groovy where you typically don't define getters:
#Canonical
#Entity
class Fizz {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id
}
By default, JPA providers access the values of entity fields and map those fields to database columns
using the entity’s JavaBean property accessor (getter) and mutator (setter) methods. As such, the
names and types of the private fields in an entity do not matter to JPA. Instead, JPA looks at only
the names and return types of the JavaBean property accessors. You can alter this using the #javax.persistence.Access annotation, which enables you to explicitly specify the access methodology
that the JPA provider should employ.
#Entity
#Access(AccessType.FIELD)
public class SomeEntity implements Serializable
{
...
}
The available options for the AccessType enum are PROPERTY (the default) and FIELD. With
PROPERTY, the provider gets and sets field values using the JavaBean property methods. FIELD makes
the provider get and set field values using the instance fields. As a best practice, you should just stick
to the default and use JavaBean properties unless you have a compelling reason to do otherwise.
You
can put these property annotations on either the private fields or the public accessor methods. If
you use AccessType.PROPERTY (default) and annotate the private fields instead of the JavaBean
accessors, the field names must match the JavaBean property names. However, the names do not
have to match if you annotate the JavaBean accessors. Likewise, if you use AccessType.FIELD and
annotate the JavaBean accessors instead of the fields, the field names must also match the JavaBean
property names. In this case, they do not have to match if you annotate the fields. It’s best to just
be consistent and annotate the JavaBean accessors for AccessType.PROPERTY and the fields for
AccessType.FIELD.
You should never mix JPA property annotations and JPA field annotations
in the same entity. Doing so results in unspecified behavior and is very
likely to cause errors.

Can annotation be added to decelerations

Can we add annotations to the decelerations instead to the getter methods.
I'm used to this
#Column(name="Part_ID")
public Long getPartId() {
return partId;
}
Can we use it like this
#Column(name="Part_ID")
private Long partId;
Thanks all.
Ravi
Yes, you can. See section 2.2.2.2 of the Hibernate annotations documentation:
By default the access type of a class
hierarchy is defined by the position
of the #Id or #EmbeddedId
annotations. If these annotations are
on a field, then only fields are
considered for persistence and the
state is accessed via the field. If
there annotations are on a getter,
then only the getters are considered
for persistence and the state is
accessed via the getter/setter. That
works well in practice and is the
recommended approach.
So if you put your #Id on a field, then Hibernate will look at annotations on the fields for the other properties. If you put #Id on a getter, then Hibernate will look at annotations on the other getters.

Categories

Resources