I am currently defining JPA entities for a legacy database (lots of composite keys, but also single-column keys). I have created the following entity superclass:
@MappedSuperclass
public abstract class AbstractEntity<ID extends Serializable> {
public abstract ID getId();
public abstract void setId(ID id);
}
And then a superclass for composite keys (as well as a superclass for long primary key, not listed here):
@MappedSuperclass
public abstract class AbstractEmbeddedIdEntity<ID extends Serializable> extends AbstractEntity<ID> {
@EmbeddedId
private ID id;
public AbstractEmbeddedIdEntity() {
id = newId();
}
@Override
public ID getId() {
return id;
}
@Override
public void setId(ID id) {
this.id = id;
}
protected abstract ID newId();
}
And finally concrete entities like this:
@Entity
@Table(name = "firstEntity")
public class FirstEntity extends AbstractEmbeddedIdEntity<FirstEntityId> {
public FirstEntity() {
}
@Embeddable
public static class FirstEntityId implements Serializable {
@Column(name = "firstId")
private String firstId;
public FirstEntityId() {
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof FirstEntityId)) {
return false;
}
FirstEntityId other = (FirstEntityId) obj;
return
Objects.equals(firstId, other.firstId);
}
@Override
public int hashCode() {
return Objects.hash(firstId);
}
}
@Override
protected FirstEntityId newId() {
return new FirstEntityId();
}
}
Now the issue is that if I have multiple entities like this and try to access an ID property of an entity (currently with Spring Boot, eg findByIdFirstId(String firstId)
), an exception is thrown:
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [firstId] on this ManagedType [unknown]
I have debugged this and found out that in hibernate, the metamodel maps all of my entities to the same MappedSupperclass instance. During application startup, the @EmbeddedId
returned by newId()
is set to the MappedSupperclass, overwriting the ID of the previous entity. So in the end, all entities are mapped to the same MappedSupperclass, but the MappedSupperclass only has the @EmbeddedId
of the last entity.
In the above example, accessing the ID property fails because the @EmbeddedId
of the last entity doesn't have a property called "firstId" (it has been overwritten with the ID properties of the last entity).
Now I am wondering if my approach is wrong, if I am missing something or if this could be an issue with hibernate?
Complete example using spring boot available on github . Run with mvn spring-boot:run
.
This looks to me like a bug in hibernate, therefore I have created a ticket in the hibernate bug tracker . As a workaround I am now defining the ID attribute (@EmbeddedId) in the concreate entity classes instead of the abstract superclass.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.