Spring 데이터 JPA 및 최대 절전 모드 분리 엔티티가 Multi-to-Many 관계를 유지하도록 전달되었습니다.
저는 이미 지속된 다른 개체와 다대다 관계가 있는 개체를 유지하려고 합니다.
다음은 나의 지속적인 객체입니다(DB(MySql)에 이미 지속됩니다).
제품.
@Entity
@Table(name="PRODUCT")
public class Product {
private int productId;
private String productName;
private Set<Reservation> reservations = new HashSet<Reservation>(0);
@Id @GeneratedValue(strategy=GenerationType.AUTO)
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
@Column(nullable = false)
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "products")
public Set<Reservation> getReservations() {
return reservations;
}
public void setReservations(Set<Reservation> reservations) {
this.reservations = reservations;
}
}
여기 지속되지 않는 개체가 있습니다. 이 개체를 생성하려고 합니다.
@Entity
@Table(name = "RESERVATION")
public class Reservation {
private int reservationId;
private Set<Product> products = new HashSet<Product>(0);
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public int getReservationId() {
return reservationId;
}
public void setReservationId(int reservationId) {
this.reservationId = reservationId;
}
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "product_reservation", joinColumns = { @JoinColumn(name = "reservationId", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "productId",
nullable = false, updatable = false) })
public Set<Product> getProducts() {
return products;
}
public void setProducts(Set<Product> products) {
this.products = products;
}
}
이것은 나의ReservationService
제품 이름 배열을 수신하는 클래스는 이름을 사용하여 제품을 살펴보고 예약 개체에 넣습니다.
@Service
public class ReservationServiceImpl implements ReservationService {
@Autowired
private ProductDAO productDAO;
@Autowired
private ReservationDAO reservationDAO;
@Transactional
public void createReservation(String[] productNames) {
Set<Product> products = new HashSet<Product>();
for (String productName : productNames) {
Product pi = productDAO.findByProductName(productName);
products.add(pi);
}
Reservation reservation = new Reservation();
reservation.setProducts(products);
reservationDAO.save(reservation); ---> Here I am getting detached entity passed to persist
}
}
여기 내꺼ProductDAO
인터페이스:
public interface ProductDAO extends JpaRepository<Product, Integer> {
public Product findByProductName(String productName);
}
다음은 내 스프링 구성 파일입니다.
@Configuration
@PropertySource(value = { "classpath:base.properties" })
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.reservation.dao")
public class RepositoryConfig {
@Autowired
private Environment env;
@Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public PlatformTransactionManager transactionManager() {
EntityManagerFactory factory = entityManagerFactory().getObject();
return new JpaTransactionManager(factory);
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(Boolean.valueOf(env
.getProperty("hibernate.generate.ddl")));
vendorAdapter.setShowSql(Boolean.valueOf(env
.getProperty("hibernate.show_sql")));
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
jpaProperties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource());
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.reservation.service.domain");
factory.setJpaProperties(jpaProperties);
factory.afterPropertiesSet();
factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
return factory;
}
@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
}
다음은 전체 스택 추적입니다.
심각: 경로 [/web]에서 servlet [dispatcher]에 대한 servlet.service()가 예외 [요청 처리 실패, 중첩 예외는 org.springframework.dao입니다.잘못된 DataAccessApiUsageException: 분리된 엔티티가 persist: com.reservation에 전달되었습니다.service.domain.제품. 중첩 예외는 org.hibernate입니다.persistentObjectException: 분리된 엔티티가 persist: com.reservation으로 전달되었습니다.service.domain.제품]과(와) 근본 원인 org.hibernate.persistentObjectException: 분리된 엔티티가 persist: com.reservation으로 전달되었습니다.service.domain.org.hibernate.event.internal에 있는 제품입니다.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
저도 같은 문제를 가지고 있었고 그것을 제거함으로써 해결했습니다.cascade = CascadeType.PERSIST
.
사용하는 경우CascadeType.ALL
이는 설명서에 따라 PERST를 사용하는 것과 동일합니다.
연결된 엔티티로 전파되는 계단식 작업 집합을 정의합니다.값 캐스케이드=ALL은 캐스케이드={와 같습니다.지속, 병합, 제거, 새로 고침, 분리}.
이는 예약을 저장하려고 할 때를 의미합니다.reservationDAO.save(reservation)
또한 연결된 제품 개체를 유지하려고 시도합니다.그러나 이 개체는 이 세션에 연결되어 있지 않습니다.그래서 오류가 발생합니다.
예약을 저장할 때 최대 절전 모드가 관련 제품을 유지하려고 할 때 예외가 발생합니다.제품의 ID에 주석이 달렸기 때문에 ID가 없는 경우에만 제품을 유지할 수 있습니다.
@GeneratedValue(strategy=GenerationType.AUTO)
그러나 저장소에서 제품을 가져왔으며 해당 ID는 null이 아닙니다.
문제를 해결하기 위한 두 가지 옵션이 있습니다.
- 거한제를 합니다.
(cascade = CascadeType.ALL)
. - 는또제를 제거합니다.
@GeneratedValue(strategy=GenerationType.AUTO)
ID 에 ID 라따의 에 있습니다.
코드에서 관계의 양쪽이 제대로 유지되는지 확인해야 합니다.
아래와 같이 예약을 업데이트한 후 해당 메소드를 제품에 추가합니다.
@Entity
@Table(name = "RESERVATION")
public class Reservation {
private int reservationId;
private Set<Product> products = new HashSet<Product>(0);
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public int getReservationId() {
return reservationId;
}
public void setReservationId(int reservationId) {
this.reservationId = reservationId;
}
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "product_reservation", joinColumns = { @JoinColumn(name = "reservationId", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "productId",
nullable = false, updatable = false) })
public Set<Product> getProducts() {
//force clients through our add and remove methods
return Collections.unmodifiableSet(products);
}
public void addProduct(Product product){
//avoid circular calls : assumes equals and hashcode implemented
if(! products.contains(product){
products.add(product);
//add method to Product : sets 'other side' of association
product.addReservation(this);
}
}
public void removeProduct(Product product){
//avoid circular calls: assumes equals and hashcode implemented:
if(product.contains(product){
products.remove(product);
//add method to Product: set 'other side' of association:
product.removeReservation(this);
}
}
}
제품의 경우:
public void addReservation(Reservation reservation){
//assumes equals and hashcode implemented: avoid circular calls
if(! reservations.contains(reservation){
reservations.add(reservation);
//add method to Product : sets 'other side' of association
reservation.addProduct(this);
}
}
public void removeReservation(Reservation reservation){
//assumes equals and hashcode implemented: avoid circular calls
if(reservations.contains(reservation){
reservations.remove(reservation);
//add method to Product : sets 'other side' of association
reservation.reomveProduct(this);
}
}
이제 제품 또는 예약에 대한 저장을 호출할 수 있으며 모든 것이 예상대로 작동하므로 행복할 것입니다.
@ 캐스케이드 유형을 제거합니다.모두 @ManytoMany 관계에서, 이것은 저에게 효과가 있었습니다.
저도 비슷한 문제가 있었어요.교체했습니다CascadeType.ALL
와 함께CascadeType.MERGE
그리고 그것은 저에게 효과가 있었습니다.
매핑은 다음과 같을 수 있습니다.ManyToMany
또는OneToOne
.
entityManager.merge()
좋은 선택입니다.세션에서 분리된 개체를 병합합니다.캐스케이드 유형을 변경할 필요가 없습니다.
저는 당신의 주석이 약간 틀렸다고 생각합니다.별로 그렇지는 않지만, 여기 예제 7.24를 보고 주석과 일치하는지 확인하십시오.무시합니다.Collection
하지만 데이터 유형, 사용하는 데 문제가 없어야 하기 때문입니다.Set
저는 당신이 a를 놓치고 있다는 것을 알아챘습니다.cascade=CascadeType.ALL
의 신의에Product
하지만 그게 문제인지 아닌지는 알 수가 없습니다.
은 당신의 입니다.Product
개체가컬렉 저할고려저않장았때의 할 때 .Product
주석에 그래서 당신의 주석에 문제가 있다고 생각합니다.
시험해 보고 어디든 있으면 알려주세요.
저장 및 병합을 사용하여 업데이트해야 하지만 먼저 ID가 null인지 확인해야 합니다.
@Override
public Registration save(Registration registration) {
if(registration.getId() == null) {
_entityManager.persist(registration);
}else {
_entityManager.merge(registration);
}
return registration;
}
언급URL : https://stackoverflow.com/questions/23645091/spring-data-jpa-and-hibernate-detached-entity-passed-to-persist-on-manytomany-re
'prosource' 카테고리의 다른 글
Oracle 구문 - 기존 구문과 새 구문 중 하나를 선택해야 합니까? (0) | 2023.08.11 |
---|---|
모듈을 찾을 수 없음: 오류:'crypto'를 확인할 수 없습니다. (0) | 2023.08.11 |
Powershell에서 유형 [System]을(를) 찾을 수 없습니다.창문들.Forms.KeyEventHandler] (0) | 2023.08.11 |
CakePHP - 마지막 쿼리 실행 가져오기 (0) | 2023.08.06 |
텍스트 파일의 내용을 자바스크립트 변수로 로드하려면 어떻게 해야 합니까? (0) | 2023.08.06 |