'Spring Data JPA / Hibernate "Unable to locate Attribute with the given name"
We have a problem with a Spring Web Application and Hibernate. It is written in Kotlin. We have an abstract Entity
@Inheritance(strategy = InheritanceType.JOINED)
abstract @Entity class ContactLogEntry protected constructor() {
@GeneratedValue @Id val id: Long = 0
@ManyToOne
@JoinColumn
protected lateinit var _contact: AbstractContact
open val contact: AbstractContact? get() = _contact
@ManyToOne
protected var _user: User? = null
open val user: User? get() = _user
And some of those:
@Entity class MailLogEntry() : ContactLogEntry() {
override var contact: Lead
get() = super.contact as Lead
set(value) {
super._contact = value
}
override var user: Telephonist
get() = super.user as Telephonist
private set(value) {
super._user = value
}
Note that "Lead" inherits directly from "AbstractContact". The Problem is with the property contact
. The User Property, where Telephonist inherits directly from User, works fine.
We get Unable to locate Attribute with the the given name [contact] on this ManagedType (PATH to ContactLogEntry)
We did it the same way before, where it works. Really no clue whats wrong.
Solution 1:[1]
In my case, using pure java, the cause was that an abstract @MappedSuperClass defined abstract getter/setter methods according to an interface, but did not define the actual member field.
The error went away after removing the getter/setter methods from the abstract class, there was no need for them after all. HTH
Solution 2:[2]
A wider possibility is that you refactorized an attribute name but with an inconsistency in a:
- getter and/or setter
- @Query
- @NamedEntityGraphs
- @NamedQuery
Solution 3:[3]
This answer applies only to Kotlin.
Changing the access type may solve the error also (in my case it did), if it is the case that one is relying on getter and setter access but the default has been set to field access.
Use
@Access(AccessType.PROPERTY)
in order for getter and setter to be used.Use
@Access(AccessType.FIELD)
in order for the field itself to be used.
As explained in more detail in this helpful article:
By default, you specify the access strategy implicitly by annotating your primary key attribute or its getter method with an
@Id
annotation. If you annotate the attribute itself, Hibernate uses field-based access.[...] And if you annotate a getter method with the
@Id
annotation, Hibernate uses property-based access to set and read the attributes of this entity.Override the default access strategy
If you want to mix both access strategies within one entity or a hierarchy of entities, you need to override the default strategy with an
@Access
annotation.
Example
In Java:
@Access(AccessType.PROPERTY)
public User getUser() { return user; }
Also, I think that in OP's case using Generics make it a little less complicated:
@Inheritance(strategy = InheritanceType.JOINED)
@Entity
abstract class ContactLogEntry<Contact: AbstractContact, UserT: User>
protected constructor() {
@GeneratedValue @Id val id: Long = 0
@ManyToOne
@JoinColumn
open var contact: Contact? = null
@ManyToOne
open var user: UserT? = null
}
@Entity class MailLogEntry : ContactLogEntry<Lead, Telephonist>()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Manos Batsis |
Solution 2 | Julio Villane |
Solution 3 |