Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
}
like image 773
smeeb Avatar asked Dec 24 '22 19:12

smeeb


1 Answers

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.

like image 131
Faraz Avatar answered Dec 26 '22 12:12

Faraz