@Embeddables 的 @ElementCollection 每个都具有 @Embeddable 字段导致“找不到设置器”异常

Posted

技术标签:

【中文标题】@Embeddables 的 @ElementCollection 每个都具有 @Embeddable 字段导致“找不到设置器”异常【英文标题】:@ElementCollection of @Embeddables each having @Embeddable field results in "Could not find a setter" exception 【发布时间】:2015-05-11 05:49:11 【问题描述】:

我有 @ElementCollection(targetClass = RideLocation.class) 的实体 Ride:

@ElementCollection(targetClass = RideLocation.class)
    @CollectionTable(name = "ride_locations", joinColumns = @JoinColumn(name = "ride_id"))
    List<RideLocation> locations = new ArrayList<>();

RideLocation 是 @Embeddable,其中包含另一个 @Embeddable:

@Embeddable
public class RideLocation 

    @Column(name = "timestamp")
    long timestamp;

    @Embedded
    Location location;

    public RideLocation(long timestamp, Location location) 
        Assert.isTrue(timestamp > 0);
        Assert.notNull(location);
        this.timestamp = timestamp;
        this.location = location;
    

    RideLocation() 
    

    public long getTimestamp() 
        return timestamp;
    

    public Location getLocation() 
        return location;
    


位置本身就是@Embeddable:

@Embeddable
public class Location 

    @Column(name = "address")
    String address;

    @Type(type = "org.hibernate.spatial.GeometryType")
    @Column(name = "point", columnDefinition = "geometry")
    Point point;

    public Location(double lat, double lng, String address) 
        this.point = wktToPoint(String.format("POINT(%.6f %.6f)", lng, lat));
        this.address = address;
    

    Location() 
    

    public String getAddress() 
        return address;
    

    public Point getPoint() 
        return point;
    

    @Transient
    public double getLat() 
        return point.getY();
    

    @Transient
    public double getLng() 
        return point.getX();
    

    private Point wktToPoint(String wktPoint) 
        WKTReader fromText = new WKTReader();
        Geometry geom = null;
        try 
            geom = fromText.read(wktPoint);
         catch (ParseException e) 
            throw new RuntimeException("Not a WKT string:" + wktPoint);
        
        geom.setSRID(4326);
        return (Point) geom;
    


看起来不错,但是这个配置给了我一个异常“在类 Location 中找不到属性地址的设置器”。

这对我来说看起来很奇怪,因为 Location 在我尝试在另一个 @Embeddable 中使用它之前,它的任何属性都不需要 setter 是 ElementCollection 的目标。

即无法正确加载集合内的第二级 @embeddable。

UPD 堆栈跟踪如下所示:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class com.dropbyke.application.JpaConfig: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.component.PojoComponentTuplizer]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:956)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:747)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
    at com.dropbyke.web.api.DropbykeApi.main(DropbykeApi.java:69)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1270)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.component.PojoComponentTuplizer]
    at org.hibernate.tuple.component.ComponentTuplizerFactory.constructTuplizer(ComponentTuplizerFactory.java:101)
    at org.hibernate.tuple.component.ComponentTuplizerFactory.constructDefaultTuplizer(ComponentTuplizerFactory.java:122)
    at org.hibernate.tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.java:81)
    at org.hibernate.mapping.Component.getType(Component.java:180)
    at org.hibernate.tuple.PropertyFactory.buildStandardProperty(PropertyFactory.java:353)
    at org.hibernate.tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.java:71)
    at org.hibernate.mapping.Component.getType(Component.java:180)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:310)
    at org.hibernate.mapping.Collection.validate(Collection.java:315)
    at org.hibernate.mapping.Set.validate(Set.java:40)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1362)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1849)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:852)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:845)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:399)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:844)
    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:1625)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)
    ... 21 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
    at sun.reflect.GeneratedConstructorAccessor28.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at org.springsource.loaded.ri.ReflectiveInterceptor.jlrConstructorNewInstance(ReflectiveInterceptor.java:1002)
    at org.hibernate.tuple.component.ComponentTuplizerFactory.constructTuplizer(ComponentTuplizerFactory.java:98)
    ... 41 common frames omitted
Caused by: org.hibernate.PropertyNotFoundException: Could not find a setter for property address in class com.dropbyke.domain.Location
    at org.hibernate.property.BasicPropertyAccessor.createSetter(BasicPropertyAccessor.java:246)
    at org.hibernate.property.BasicPropertyAccessor.getSetter(BasicPropertyAccessor.java:240)
    at org.hibernate.mapping.Property.getSetter(Property.java:328)
    at org.hibernate.tuple.component.PojoComponentTuplizer.buildSetter(PojoComponentTuplizer.java:159)
    at org.hibernate.tuple.component.AbstractComponentTuplizer.<init>(AbstractComponentTuplizer.java:65)
    at org.hibernate.tuple.component.PojoComponentTuplizer.<init>(PojoComponentTuplizer.java:59)

【问题讨论】:

一个 Embeddable 类并不意味着在数据库中有对应的表,对吧? @Column 注释在这里意味着什么?我不明白 @Prasad Kharkar 列注释清楚地表明该字段应该存储在一个名为无论列名是什么的列中......所以它没有表,但被持久化到所有者,并且必须有一列 如果说明一些错误消息,然后说明正在使用的 JPA 实现可能会有所帮助......因为它是有问题的实现。除非使用 PROPERTY 访问权限,否则您不需要 setter/getter(而您不需要) 我正在使用 Spring Boot 启动器和 JPA 的休眠实现。所有这些类都应该保留在 db 中。 List 位置集合在 @Entity Ride 内。 这可能是一个错误。这是一个类似的问题:***.com/questions/18441222/… 这里可能是一个相关的错误:hibernate.atlassian.net/browse/HHH-9089 【参考方案1】:

我很确定它在抱怨,因为您有一个带 getter 的字段 Address ,而没有 setter。 JPA 足够“聪明”,可以假设以“is”和“get”开头的方法也需要相同 val 的“set”函数。所以添加一个“setAddress”,它就会停止抱怨。

要在不使用 setter 的情况下解决此问题,只需将方法标记为“@Transient”。确保导入 javax.persistence.Transient 一个而不是 java.beans.Transient 一个,否则它仍然会失败。

【讨论】:

以上是关于@Embeddables 的 @ElementCollection 每个都具有 @Embeddable 字段导致“找不到设置器”异常的主要内容,如果未能解决你的问题,请参考以下文章

既是3的倍数又是5的倍数都有哪些

一个三位数既是3的倍数,又是5的倍数。这样的三位数最小是啥

数组的创建,及数组的方法

cnn中的步长的目的和重要性是啥

物质的运动

多态的好处??