因此,当我尝试在我的 spring 应用程序中执行更新方法时出现了一个大错误,问题出在 Caracter 类上,因为这似乎是生成它的那个类。当我在 main 中设置我的东西并尝试更新数据库中的 Anime 对象时,Caracter 类给了我下面显示的错误
代码
package com.site.anime.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.List;
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Caracter {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String image;
private String description;
private Double overall_mark;
@ManyToMany(cascade = { CascadeType.ALL })
private List<Anime> shows;
}
package com.site.anime.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Fetch;
import javax.persistence.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Anime {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String image;
private Integer no_episodes;
private String description;
private Double overall_score;
@ManyToMany(cascade = { CascadeType.ALL })
private List<Caracter> caracters;
@OneToMany(cascade = { CascadeType.ALL })
private List<Review> reviews;
@ManyToMany(cascade = { CascadeType.ALL })
private List<Category> categories;
}
package com.site.anime.service.impl;
import com.site.anime.model.Anime;
import com.site.anime.repository.RepositoryShow;
import com.site.anime.service.AnimeService;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.lang.reflect.Field;
@Service
public class AnimeServiceImpl implements AnimeService {
private final RepositoryShow repositoryShow;
public AnimeServiceImpl(RepositoryShow repositoryShow) {
this.repositoryShow = repositoryShow;
}
@Override
public Anime findFirstByName(String name) {
return repositoryShow.findFirstByName(name);
}
@Override
@Transactional
public Anime updateAnime(Anime newShow) {
Anime anime=repositoryShow.findById(newShow.getId()).orElseThrow();
//System.out.println(anime.getCaracters().get(0).getName());
if(newShow.getName()!=null){
anime.setName(newShow.getName());
}
if(newShow.getImage()!=null){
anime.setImage(newShow.getImage());
}
if(newShow.getNo_episodes()!=null){
anime.setNo_episodes(newShow.getNo_episodes());
}
if(newShow.getDescription()!=null){
anime.setDescription(newShow.getDescription());
}
if(newShow.getCaracters()!=null){
anime.setCaracters(newShow.getCaracters());
}
if(newShow.getCategories()!=null){
anime.setCategories(newShow.getCategories());
}
return anime;
//anime=newShow;
// Field[] fields = anime.getClass().getDeclaredFields();
// Field[] fields1 = newShow.getClass().getDeclaredFields();
// for(int i=0;i<fields.length;i++){
// if(fields[i]!=fields1[i]){
// fields[i]=fields1[i];
// }
// }
//return null;
}
}
package com.site.anime;
import com.site.anime.model.*;
import com.site.anime.repository.*;
import com.site.anime.service.impl.AnimeServiceImpl;
import com.site.anime.service.impl.CaracterServiceImpl;
import com.site.anime.service.impl.UserServiceImpl;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@EnableJpaRepositories
@SpringBootApplication
public class AnimeApplication {
public static void main(String[] args) {
SpringApplication.run(AnimeApplication.class, args);
}
@Bean
CommandLineRunner init(RepositoryShow repositoryShow, RepositoryCategory repositoryCategory,
RepositoryCaracter repositoryCaracter, RepositoryUser repositoryUser,
RepositorySuperUser repositorySuperUser, ProfileRepository profileRepository, AnimeServiceImpl animeService,
CaracterServiceImpl caracterService, UserServiceImpl userService){
return args -> {
List<Anime> shows=new LinkedList<>();
Caracter caracter=new Caracter(null,"Subaru","","",0.0,null);
List<Caracter> caracters=new LinkedList<>();
caracters.add(caracter);
Profile profile=new Profile(null,"","",18,"",null,null,null,null,null);
Utilizator user=new Utilizator(null);
user.setName("rusu");
//Review review=new Review(null,user,"",0);
Review review=new Review(null,"",2,null,null,null);
Review review1=new Review(null,"",5,null,null,null);
List<Review> reviews=new LinkedList<>();
review.setUser(user);
review1.setUser(user);
reviews.add(review);
reviews.add(review1);
//profile.setUser(user);
Anime show=new Anime(null,"ReZero Season 1","",25,"",0.0,null,reviews,null);
shows.add(show);
caracter.setShows(shows);
show.setCaracters(caracters);
review.setReviewed_show(show);
review1.setReviewed_show(show);
profile.setReviews(reviews);
user.setProfile(profile);
repositoryShow.save(show);
repositoryCaracter.save(caracter);
repositoryUser.save(user);
System.out.println(animeService.findFirstByName("ReZero Season 1").getName());
//System.out.println(repositoryUser.findFirstByName("rusu").getName());
Anime show1=new Anime(null,"ReZero Season 2","",25,"",0.0,null,reviews,null);
System.out.println(caracterService.findFirstByName("Subaru").getName());
System.out.println(userService.findFirstByName("rusu").getName());
//System.out.println(animeService.findFirstByName("ReZero Season 1"));
Utilizator user1=new Utilizator(null);
List<Review> reviews1=new LinkedList<>();
Review review2=new Review(null,"",2,null,null,null);
Profile profile1=new Profile(null,"","",18,"",null,null,null,null,null);
review2.setUser(user1);
review2.setReviewed_show(show);
reviews1.add(review2);
profile1.setReviews(reviews1);
user1.setProfile(profile1);
repositoryUser.save(user1);
show.setName("ReZero Season 2");
animeService.updateAnime(show);
userService.deleteUser(user1);
};
}
}
和错误
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:807) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.3.jar:2.4.3]
at com.site.anime.AnimeApplication.main(AnimeApplication.java:23) ~[classes/:na]
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.site.anime.model.Caracter; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.site.anime.model.Caracter
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:297) ~[spring-orm-5.3.4.jar:5.3.4]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233) ~[spring-orm-5.3.4.jar:5.3.4]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566) ~[spring-orm-5.3.4.jar:5.3.4]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-5.3.4.jar:5.3.4]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-5.3.4.jar:5.3.4]
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654) ~[spring-tx-5.3.4.jar:5.3.4]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407) ~[spring-tx-5.3.4.jar:5.3.4]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.4.jar:5.3.4]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.4.jar:5.3.4]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.4.jar:5.3.4]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.4.jar:5.3.4]
at com.site.anime.service.impl.AnimeServiceImpl$$EnhancerBySpringCGLIB$$3ebceda5.updateAnime(<generated>) ~[classes/:na]
at com.site.anime.AnimeApplication.lambda$init$0(AnimeApplication.java:91) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) ~[spring-boot-2.4.3.jar:2.4.3]
... 5 common frames omitted
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.site.anime.model.Caracter
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:120) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:104) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:765) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:341) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:492) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:416) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:525) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:456) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:419) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:151) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:93) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1362) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:453) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3212) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2380) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562) ~[spring-orm-5.3.4.jar:5.3.4]
... 16 common frames omitted
答案 0 :(得分:0)
我认为这里的问题是,您正在用新集合替换字符集合,并且该集合具有与持久性上下文不同的对象,尽管它使用相同的主键。由于您正在级联更改,Hibernate 尝试刷新更改并意识到该主键的实体已经与持久性上下文相关联,并且无法刷新您看到的异常。如果您只想将实体应用于数据库,请尝试使用 entityManager.merge
而不先加载实体。或者,您也可以尝试应用这样的集合:
if (newShow.getCaracters()!=null) {
for (Character c : newShow.getCaracters()) {
anime.getCaracters().add(entityManager.getReference(Character.class, c.getId());
}
}
if (newShow.getCategories()!=null) {
for (Category c : newShow.getCategories()) {
anime.getCategories().add(entityManager.getReference(Category.class, c.getId());
}
}