Spring boot:在域模型上定义自定义方法

问题描述 投票:0回答:1

我在 feedLocation 上收到一个字符串编码位置,并且我定义了一种方法来将字符串分割为三个坐标 x、y、z。

public class Feedback {
    @Column(name = "feedback_id")
    private @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="my_entity_seq_gen") Integer feedbackId;
    @Column(name = "feed_date", columnDefinition= "TIMESTAMP WITH TIME ZONE DEFAULT clock_timestamp()")
    private LocalDateTime feedDate;
    @Column(name = "sens_code")
    private String sensCode;
    @Column(name = "feed_value")
    private Double feedValue;
    @Column(name = "location")
    private String feedLocation;
    @Transient
    private Double longitude = coordinates("x");
    @Transient
    private Double latitude = coordinates("y");
    @Transient
    private Double altitude = coordinates("z");

}

Coorrdinates 方法获取的字符串坐标仍然为空,导致编译失败。

public Double coordinates(String coordinate){
            
        String wkbString = feedLocation;
        
        WKBReader reader = new WKBReader();
 
        Geometry geometry;
        
        try {
            geometry = reader.read(Hex.decodeHex(wkbString.toCharArray()));
        } catch (ParseException | DecoderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
 
        String geometryText = geometry.toString();
     
        if (geometry.getGeometryType().equalsIgnoreCase("Point")) {
            
            double latitude = geometry.getCoordinate().y;
            double longitude = geometry.getCoordinate().x;
            double altitude = geometry.getCoordinate().z; 

            switch (coordinate) {
                case "x":
                    return longitude;
                case "y":
                    return latitude;
                case "z":
                    return altitude;                
            }
            
            return null;
        }

        return null;
    }

我希望在这三个坐标上获得正确的值,但是当我编译时出现错误,因为当类初始化时feedLocation仍然为空。

堆栈跟踪:

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
    at com.IOTProjectUI.Application.main(Application.java:26)
    ... 5 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800)
    ... 21 more
Caused by: org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
    at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:123)
    at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77)
    at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:181)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:319)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1498)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
    ... 25 more
Caused by: org.hibernate.InstantiationException: could not instantiate test object : com.IOTProjectUI.domain.Feedback
    at org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:43)
    at org.hibernate.engine.internal.UnsavedValueFactory.getUnsavedIdentifierValue(UnsavedValueFactory.java:68)
    at org.hibernate.tuple.PropertyFactory.buildIdentifierAttribute(PropertyFactory.java:65)
    at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:142)
    at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:613)
    at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:126)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96)
    ... 33 more
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:40)
    ... 44 more
Caused by: java.lang.NullPointerException: Cannot invoke "String.toCharArray()" because "wkbString" is null
    at com.IOTProjectUI.domain.Feedback.coordinates(Feedback.java:98)
    at com.IOTProjectUI.domain.Feedback.<init>(Feedback.java:66)
    ... 50 more
java spring spring-boot
1个回答
0
投票

为了解决您的问题,您应该将坐标的计算移至 getter 方法:

public class Feedback {
    @Column(name = "feedback_id")
    private @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="my_entity_seq_gen") Integer feedbackId;
    @Column(name = "feed_date", columnDefinition= "TIMESTAMP WITH TIME ZONE DEFAULT clock_timestamp()")
    private LocalDateTime feedDate;
    @Column(name = "sens_code")
    private String sensCode;
    @Column(name = "feed_value")
    private Double feedValue;
    @Column(name = "location")
    private String feedLocation;

    public Double getLongitude() {
        return coordinates("x");
    }

    public Double getLatitude() {
        return coordinates("y");
    }

    public Double getAltitude() {
        return coordinates("z");
    }
}

这样,您将避免在对象初始化期间计算字段,而是在需要时计算它们。

请记住,每次使用此方法都会重新计算字段。

为了避免这种情况,您可以使用

@PostLoad
注释来代替:

public class Feedback {
    @Column(name = "feedback_id")
    private @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="my_entity_seq_gen") Integer feedbackId;
    @Column(name = "feed_date", columnDefinition= "TIMESTAMP WITH TIME ZONE DEFAULT clock_timestamp()")
    private LocalDateTime feedDate;
    @Column(name = "sens_code")
    private String sensCode;
    @Column(name = "feed_value")
    private Double feedValue;
    @Column(name = "location")
    private String feedLocation;
    @Transient
    private Double longitude;
    @Transient
    private Double latitude;
    @Transient
    private Double altitude;

    @PostLoad
    private void postLoad() {
        this.longitude = coordinates("x");
        this.latitude = coordinates("y");
        this.altitude = coordinates("z");
    }
}

有关更多详细信息,请查看这篇优秀的博客文章:https://vladmihalcea.com/how-to-map-calculated-properties-with-jpa-and-hibernate-formula-annotation/

© www.soinside.com 2019 - 2024. All rights reserved.