#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 предоставляют удобный способ создания неизменяемых списков».Таким образом, это означает, что перед отправкой вашего объекта в базу данных вы должны убедиться, что ваши объекты списка являются неизменяемыми / не динамическими.