I've one persistent class that has one transient field representing the API version of this class (subset of the fields that I user for api requests). This field is @Transient
as I simple use the other fields to create it.
The problem is that hibernate uses the default empty constructor to instantiate the class and reflection to access the fields... so i can't instantiate my transient class on constrorctor nor on the call of setter methods
I tried to anotate the getter method instead of the field to force hibernate to use the setter, but it didn't work
I tried to use @Access(AccessType.PROPERTY)
on the fields but it didn't work
how to force hibernate call setter methods to fill class fields?
@Entity
public class User {
@Transient
private ApiUser tempUser = new ApiUser ();
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Access(AccessType.PROPERTY)
@Column(nullable = false)
private String name;
@Access(AccessType.PROPERTY)
@Column(nullable = false, unique = true)
private String username;
@Access(AccessType.PROPERTY)
@Column(nullable = false)
private String userId;
//lots of others fields//
public void setUsername(String username) {
this.username = username;
this.tempUser.setUsername(username);
}
public void setUserId(String userId) {
this.userId = userId;
this.tempUser.setId(Long.parseLong(userId));
}
@Access in hibernate is used to force access hierarchy of an entity methods and fields. In class when we use @Id or @Embedded on field, then field is persisted and used to access data by setter and getter. If @Id or @Embedded is used on property then access hierarchy will be property.
Hibernate will no longer use the getters and setters, but will access the fields directly via reflection, meaning if you have any special logic in your getters and setters, it will no longer be called.
As a JPA provider, Hibernate can introspect both the entity attributes (instance fields) or the accessors (instance properties). By default, the placement of the @Id annotation gives the default access strategy. When placed on a field, Hibernate will assume field-based access.
You may use lombok - to manually avoid getter and setter method. But it create by itself. The using of lombok significantly reduces a lot number of code. I found it pretty fine and easy to use.
By default the access type is defined by the place where you put your identifier annotation (@Id). If you put it on the field - it will be AccessType.FIELD, if you put it on the getter - it will be AccessType.PROPERTY.
Sometimes you might want to annotate not fields but properties (e.g. because you want to have some arbitrary logic in the getter or because you prefer it that way.) In such situation you must define a getter and annotate it as AccessType.PROPERTY.
As far as I remember, if you specify either AccessType.FIELD or AccessType.PROPERTY on any of the entity fields / methods you must specify the default behaviour for the whole class. And that's why you need to have AccessType.FIELD on the class level (despite that AccessType.FIELD is the default value.)
Now, if you wouldn't have @Transient on the phnnumber field, the JPA would provide you with a 3 columns table:
id, phnnumber, getphnnumber. That's because it would use AccessType.FIELD for all of the entity fields (id and phnnumber) and, at the same time, it'd use AccessType.PROPERTY for your getter (getPhnnumber()). You'll end with phone number mapped twice in the database.
Therefore, the @Transient annotation is required - it means that the entity won't store the value of the field in the underlying storage but the value returned by your getter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With