0

We are using some @Embeddable beans within some JPA Entities for better code structure and reuse. What I'm wondering is: every example I come across provides setters and getters for the @Embedded objects. Why? I tried just having them as final fields - that works, too, and makes much sense in our case, since the embedded stuff is always present. Is there some disadvantage of this that I am not aware of?

For example: usually it is done that way:

@Embeddable
public class Address {
    // ...
}

@Entity
public class Person {
    @Embedded
    private Address address;

    public void setAddress(Address address) {
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }
}

Is there any trouble when I write Person this way, when there is always an Address:

@Entity
public class Person {
    @Embedded
    private final Address address = new Address();

    public Address getAddress() {
        return address;
    }
}
Dr. Hans-Peter Störr
  • 25,298
  • 30
  • 102
  • 139
  • While it turns out that making things final is, at least, unpleasant (compare the answer of @NeilStockton http://stackoverflow.com/a/39416643/21499) there is also the aspect that JPA sets embeddable beans to null when all their fields are null , http://stackoverflow.com/q/1324266/21499 . So I went with removing the setter but creating Person.address in the getter if yet null. – Dr. Hans-Peter Störr Sep 12 '16 at 16:55

1 Answers1

3

You cannot persist final or static fields, and that applies whether embedded or non-embedded. The JPA spec is very clear about that, as are documents for the different JPA providers.

JPA Spec $2.1

The entity class must not be final. No methods or persistent instance variables of the entity class may be final.

Neil Stockton
  • 11,383
  • 3
  • 34
  • 29
  • Thanks! Puzzlingly, it does work, anyway: I tried with Hibernate 5. Perhaps this doesn't really apply here. After all, Person.address might or might not count as a persisted instance variable - it's just its attributes that are actually persisted, here, and not Person.address itself, don't you think? – Dr. Hans-Peter Störr Sep 09 '16 at 17:34
  • 1
    The FIELD has to be set by the JPA provider, embedded or not. It applies here. That's all that can be said for portability. – Neil Stockton Sep 10 '16 at 06:33
  • OK, I believe you. :-) I checked what happens when hibernate handles this, and it seems it actually changes the final field Person.address to a new object, ignoring the protection by "final". This does work, but sounds quite unpleasant and perpexing, and this means that Address is instantiated twice for one Person instantiation when loading a bean. I'm not quite sure when and where to instantiate Address in my setting, though. – Dr. Hans-Peter Störr Sep 12 '16 at 10:41