1

An Owner entity has a @ManyToOne - @OneToMany relationship with the teacher entity. When I annotate each like this

@Entity
public class Product {

... 

@ManyToOne(cascade = MERGE)
private final Owner owner;

On the other side, in the Owner Class,

@Entity 
public class Owner {

...

@OneToMany(mappedBy = "owner", cascade = MERGE)
private final List<Product> products;

What happens now is that "owner" in the line mappedBy = "owner" turns red. Hovering over it, I get the error that the owner attribute cannot be found.

The error: Cannot find inverse attribute

The solution was simply to remove the final keyword in the attribute owner in the Product class.

It becomes private Owner owner and the error disappears. I don't understand why adding the keyword final causes this problem.

Why does this happen? Is there a workaround? Can I still make the owner attribute final?

The main idea from the getgo was to make the product class immutable. While this is a challenge, I've managed to find a workaround for most things, but I didn't know how to fix this problem.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
Yelderiny
  • 13
  • 5

2 Answers2

1

JPA does not support immutability. A JPA entity does require a default constructor and getters and setters for properties. And the fields must not be final.

Technically it would be possible to implement an ORM that ignores final attributes but why should it?

The keyword final says: This gets assigned a value at construction time and never changes after that. This is just not true for JPA entities which get constructed via no-args-constructor and then populated in second step.

If you are looking for an ORM that has better support for immutable classes (constructor with arguments, "wither" methods) you might want to check out Spring Data JDBC.

Full disclosure: I'm Spring Data developer working on both Spring Data JPA and Spring Data JDBC.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
  • but conceptually is there a meaning to immutable entity classes? instances of all such classes are bound with the persistent layer making them unique by default isn't it? – Juliyanage Silva Apr 01 '22 at 12:25
  • 1
    JPA makes entities unique since in the sense of one instance (type, id) tuple. Therefore immutable entities can't really work with JPA since they require creation of new instances with same id and type to model change. But that is just a choice JPA made. Spring Data JDBC made very different choices. – Jens Schauder Apr 01 '22 at 12:29
  • That's really interesting. I didn't know there were major differences between the JDBC and JPA. @JensSchauder which one would you recommend using in general? and when would you use one over the other? – Yelderiny Apr 02 '22 at 16:04
  • I consider SD JDBC to be conceptually cleaner and therefore easier to understand and would prefer it for any new project. But SD JDBC is "my baby" so I'm highly biased. Either way I recommend to read https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates – Jens Schauder Apr 03 '22 at 17:49
0

I think you have understood immutability concept wrong. Immutability is a concept being forced by the Java language. For example String class is immutable because of the security, caching etc. But in your case Product is an entity class and if you save it in a persistent layer, it is already unique on it's own. So even if you make the Product class immutable, how are you going to keep that consistency during two application loads?. If you are trying to make a Product having owned by only one owner, then do a db check rather than trying to make it immutable in memory.

Juliyanage Silva
  • 2,529
  • 1
  • 21
  • 33
  • I see. Does that mean that having the keyword final on the rest of the attributes of the class is also unnecessary? – Yelderiny Apr 01 '22 at 10:41