Reputation: 2105
I have the following classes (simplified) :
Represents a geographic zone
@Entity
@Table(name = "location")
public class Location extends DomainObject {
@OneToMany(mappedBy = "lastPositionHistoric.location")
private Set<Thing> things = new LinkedHashSet<>(0);
public Location() {
}
public Set<Thing> getThings(){
return things;
}
public void setThings(Set<Thing> things){
this.things = things;
}
}
Represents a moving asset
@Entity
@Table(name = "thing")
public class Thing extends DomainObject {
@OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name = "last_position_thing_historic_id")
private ThingHistoric lastPositionHistoric;
public Thing() {
}
public ThingHistoric getLastPositionHistoric() {
return lastPositionHistoric;
}
public void setLastPositionHistoric(ThingHistoric lastPositionHistoric) {
this.lastPositionHistoric = lastPositionHistoric;
}
}
Represents a GPS history of a Thing (I have removed unrelevant GPS properties for the problem)
@Entity
@Table(name = "thing_historic")
public class ThingHistoric extends DomainObject {
@ManyToOne(cascade = {CascadeType.REFRESH, CascadeType.MERGE}, fetch = FetchType.EAGER)
@JoinColumn(name = "thing_id", nullable = false)
@NotNull
private Thing thing;
@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.REFRESH})
@JoinColumn(name = "location_id")
private Location location;
public ThingHistoric() {
}
public Thing getThing() {
return thing;
}
public ThingHistoric setThing(Thing thing) {
this.thing = thing;
return this;
}
public Location getLocation() {
return location;
}
public ThingHistoric setLocation(Location location) {
this.location = location;
return this;
}
}
Each Thing moves in the real world and can be at a given time inside a location or in no location.
When a Thing is inside a location, the lastPositionHistoric object has its location value equal to the Location the thing is inside.
When I added the things field inside the Location class, Hibernate started to complain with the following error :
Caused by: java.lang.ClassCastException: org.hibernate.mapping.ManyToOne cannot be cast to org.hibernate.mapping.Component
at org.hibernate.mapping.PersistentClass.getRecursiveProperty(PersistentClass.java:465)
at org.hibernate.mapping.PersistentClass.getRecursiveProperty(PersistentClass.java:421)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:763)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:724)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:54)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1621)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1589)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:848)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:876)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 52 more
I don't understand why because the mapping seems correct to me. The list of things inside a location should be all the things that have lastPositionHisotric.location equals to the given location, right ?
Is it a bug or does my mapping is definitely wrong ?
Upvotes: 1
Views: 1905
Reputation: 11531
"." (dot) notation in mappedBy
is to refer to fields within embedded attributes (see JPA spec 11.1.4.1 for example). It is not for use with entities! And I don't see anything embedded in your mappings. So yes your mapping is definitely wrong
The dot (".") notation syntax must be used in the mappedBy element to indicate the relationship attribute within the embedded attribute. The value of each identifier used with the dot notation is the name of the respective embedded field or property.
Upvotes: 2