Добавление в список, который является элементом в классе Java Spring

#java #spring-boot #spring-mvc

#java #spring-boot #spring-mvc

Вопрос:

У меня есть класс Account для приложения поиска работы, которое я создаю, Которое содержит связанный список экземпляров Education (только название университета, средний балл и т. Д.). Я хотел бы иметь запрос HTTP Post для добавления элемента в этот список:

 @PostMapping("/education/{id}")
    void newAccount(@RequestBody Education newEducation, @PathVariable Long id) {
        Account a = repository.findById(id).orElseThrow(() -> new AccountNotFoundException(id));
        a.addEducation(newEducation);
    }
  

Это класс account:

 
import java.util.LinkedList;
import java.util.Objects;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Account {
    private @Id @GeneratedValue Long id;
    private String name;
    private String email;
    private String phone;
    private LinkedList<Education> education;
    Account() {}
    Account(String name, String email, String phone) {
        education = new LinkedList<>();
        this.setName(name);
        this.setEmail(email);
        this.setPhone(phone);
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id=id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public LinkedList<Education> getEducation() {
        return education;
    }
    public void addEducation(Education e) {
        education.add(e);
    }
    @Override
    public boolean equals(Object o) {
        if (this==o)
            return true;
        if (!(o instanceof Account))
            return false;
        Account acc = (Account)o;
        return name.equals(acc.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(this.id, this.name);
    }
    @Override
    public String toString() {
        String edu="";
        if (!this.education.isEmpty())
        {
            edu =", "Education: [";
            for (Education e: this.education)
            {
                edu =e.toString();
            }
            edu ="]";
        }
        String s = "Account{";
        
        s  = String.format(""id": "%s", ", this.id);
        s  = String.format(""name": "%s", ", this.name);
        s  = String.format(""email": "%s", ", this.email);
        s  = String.format(""phone": "%s"", this.phone);
        s  = edu;
        
        s  = "}";
        return s;
    }
}

  

Однако, когда я фактически отправляю post-запрос с данными об образовании (для уже существующего пользователя), он не публикует его. Он правильно печатает учетную запись a (с добавленным образованием), но фактически не обновляет базу данных.

Кроме того, это еще один класс, который у меня есть:

 import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class LoadDatabase {
    private static final Logger log = 
            LoggerFactory.getLogger(LoadDatabase.class);
    
    @Bean
    CommandLineRunner initDatabase(AccountRepository repository) {
        return args -> {
            log.info("Preloading "   repository.save(new Account("Alex", "ax@b.com", "214")));
            Account a= new Account("Bob", "bob@n.com", "972");
            //a.addEducation(new Education("B.S.", "Uni", 3.64));
            //log.info("Preloading "   repository.save(a));
            
        };
    }

}

  

Раскомментирование.addEducation и log.info вызывает ошибку времени выполнения (сохранение любого из них не приведет к этому):

java.lang.Исключение IllegalStateException: не удалось выполнить CommandLineRunner в org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~ [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779) ~ [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~ [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~ [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.boot.SpringApplication.run(SpringApplication.java: 1226) ~ [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] в com.project933.Project933Application.main(Project933Application.java: 10) ~ [classes/:na] Вызвано: org.springframework.orm.jpa.JpaSystemException: не удалось выполнить сериализацию; вложенным исключением является org.hibernate.type.Исключение SerializationException: не удалось выполнить сериализацию в org.springframework.orm.jpa.vendor.Исключение HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:353) ~ [spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE] в организации.springframework.orm.jpa.vendor.HibernateJpaDialect.translateexceptionесли возможно (HibernateJpaDialect.java:255) ~ [spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528 ) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61 ) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) ~ [spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:154 ) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] вorg.springframework.aop.framework.ReflectiveMethodInvocation.продолжить (ReflectiveMethodInvocation.java:186) ~ [spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178 ) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.aop.framework.ReflectiveMethodInvocation.продолжить (ReflectiveMethodInvocation.java:186) ~ [spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95 ) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] вorg.springframework.aop.framework.ReflectiveMethodInvocation.продолжить (ReflectiveMethodInvocation.java:186) ~ [spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в com.sun.proxy.$Proxy90.save(неизвестный источник) ~ [na:na] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) ~[na:na] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~ [na:na] в java.base/jdk.internal.reflect.Делегирование methodaccessorimpl.invoke(делегирование methodaccessorimpl.java:43) ~[na:na] в java.base/java.lang.reflect .Метод.invoke(Method.java:566) ~ [na:na] в org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в com.sun.proxy.$Proxy64.save(неизвестный источник) ~ [na:na] в com.project933.LoadDatabase.lambda $0(LoadDatabase.java:19) ~[classes/:na] в org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) ~ [spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] … Пропущено 5 общих фреймов, вызванных: org.hibernate.type.Исключение SerializationException: не удалось выполнить сериализацию в org.hibernate.internal.util.SerializationHelper.serialize(SerializationHelper.java:119) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.internal.util.SerializationHelper.serialize(SerializationHelper.java:144) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.internal.util.SerializationHelper.clone(SerializationHelper.java:75) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.type.descriptor.java.SerializableTypeDescriptor$SerializableMutabilityPlan.deepCopyNotNull(SerializableTypeDescriptor.java:41 ) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.type.descriptor.java.SerializableTypeDescriptor$SerializableMutabilityPlan.deepCopyNotNull(SerializableTypeDescriptor.java:32 ) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.type.descriptor.java.MutableMutabilityPlan.deepCopy(Изменяемый изменяемый план.java:35) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.type.AbstractStandardBasicType.deepCopy(AbstractStandardBasicType.java:308) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.type.AbstractStandardBasicType.deepCopy(AbstractStandardBasicType.java:304) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.type.TypeHelper.deepCopy(TypeHelper.java:55) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:279) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.event.internal.DefaultPersistEventListener .onPersist(DefaultPersistEventListener.java:128) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.event.internal.DefaultPersistEventListener .onPersist(DefaultPersistEventListener.java:55) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:721) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] в org.hibernate.internal.SessionImpl.persist(SessionImpl.java:707) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) ~ [na:na] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] в java.base/jdk.internal.reflect .Делегирование methodaccessorimpl.invoke(делегирование methodaccessorimpl.java:43) ~[na:na] в java.base/java.lang.reflect .Метод.invoke(Method.java:566) ~ [na:na] в org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314 ) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE] в com.sun.proxy.$Proxy87.persist(неизвестный источник) ~ [na: na] в org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:554 ) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) ~ [na:na] на java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] в java.base/jdk.internal.reflect.Делегирование methodaccessorimpl.invoke(делегирование methodaccessorimpl.java:43) ~[na:na] в java.base/java.lang.reflect .Метод.invoke(Method.java:566) ~ [na:na] в org.springframework.data.repository.core.support.ImplementationInvocationMetadata.invoke(ImplementationInvocationMetadata.java:72) ~ [spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:382 ) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:205 ) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:549 ) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] в организации.springframework.aop.framework.ReflectiveMethodInvocation.продолжить (ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.data.repository.core.support.queryexecutormethod Interceptor .doInvoke(queryexecutormethod interceptor.java:155) ~ [spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130 ) ~[spring-data-commons-2.3.4.РЕЛИЗ.jar:2.3.4.RELEASE] в org.springframework.aop.framework.ReflectiveMethodInvocation.продолжить (ReflectiveMethodInvocation.java:186) ~ [spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.data.projection.Defaultmethod Invokingmethod Interceptor.invoke(defaultmethod invokingmethod interceptor.java:80) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] в org.springframework.aop.framework.ReflectiveMethodInvocation.продолжить (ReflectiveMethodInvocation.java:186) ~ [spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) ~ [spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) ~ [spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.aop.framework.ReflectiveMethodInvocation.продолжить (ReflectiveMethodInvocation.java:186) ~ [spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] в org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139 ) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] … Пропущен 21 общий фрейм, вызванный: java.io.NotSerializableException: com.project933.Обучение в java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java: 1185) ~ [na:na] в java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349) ~ [na:na] в java.base/ java.util.LinkedList.writeObject(LinkedList.java:1135) ~[na:na] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) ~ [na:na] в java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] в java.base/jdk.internal.reflect.Делегирование methodaccessorimpl.invoke(делегирование methodaccessorimpl.java:43) ~[na:na] в java.base/java.lang.reflect .Method.invoke(Method.java:566) ~[na:na] в java.base/java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1145) ~ [na:na] в java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1497)~[na:na] в java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433) ~ [na:na] в java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java: 1179) ~ [na:na] в java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349) ~ [na:na] в org.hibernate.internal.util.SerializationHelper.serialize(SerializationHelper.java:115) ~ [hibernate-core-5.4.21.Final.jar:5.4.21.Final] … 63 общих фрейма опущены

Может кто-нибудь, пожалуйста, объяснить, почему у меня возникают проблемы с вставкой экземпляров Education в базу данных Account? Я использую JpaRepository.

Спасибо!

редактировать: это учебный класс:

 public class Education {
    private String degree;
    private String institute;
    private double gpa;
    Education(String degree, String institute, double gpa) {
        this.setDegree(degree);
        this.setInstitute(institute);
        this.setGpa(gpa);
    }
    public String getDegree() {
        return degree;
    }
    public void setDegree(String degree) {
        this.degree = degree;
    }
    public String getInstitute() {
        return institute;
    }
    public void setInstitute(String institute) {
        this.institute = institute;
    }
    public double getGpa() {
        return gpa;
    }
    public void setGpa(double gpa) {
        this.gpa = gpa;
    }
    @Override
    public String toString() {
        String s = "{";
        s  = s  = String.format(""degree": "%s"", this.degree);
        s  = String.format(""institute": "%s"", this.institute);
        s  = String.format(""gpa": %.2f", this.gpa);
        s  = "}";
        return s;
    }
}

  

Ответ №1:

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/List.html

Проблема в том, что пока ваш список динамический, его нельзя сериализовать, но его необходимо сериализовать, чтобы иметь возможность передавать в базу данных. Поэтому вы должны убедиться, что ваш список сериализуем. Это достигается тем, что «Статические фабричные методы List.of и List.copyOf предоставляют удобный способ создания неизменяемых списков».Таким образом, это означает, что перед отправкой вашего объекта в базу данных вы должны убедиться, что ваши объекты списка являются неизменяемыми / не динамическими.