2014-06-11 2 views
1

아래 엔티티가 있습니다.@OrderColumn 및 @OneToMany가있는 엔티티를 저장하는 동안 ConstraintViolationException이 발생했습니다.

@Entity 
public class Shop { 
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE }, orphanRemoval = true) 
    @JoinTable(name = "shop_image", 
      joinColumns = @JoinColumn(name = "shop_id"), 
      inverseJoinColumns = @JoinColumn(name = "image_id")) 
    @OrderColumn(name = "order_number") 
    @BatchSize(size = 20) 
    private List<Image> images = new ArrayList<Image>(0); 
} 

shop_image 나타난 == (아이디 PK, shop_id, image_id, ORDER_NUMBER) 및 고유 제한 (shop_id, image_id)을 갖는다. (트랜잭션 문맥에서) 호출 코드 아래

:

  1. 모든 이미지를 삭제

    @PersistenceContext 
    EntityManager em; 
    
    @Transactional 
    // shop exist in DB 
    public void reorderImages(Shop shop) { 
        //shop.getImages().size == 2; {img0, img1} 
        List<Image> newImages = new ArrayList<>(); 
        newImages.add(shop.getImages().get(1)); 
        newImages.add(shop.getImages().get(0)); 
        shop.setImages(newImages); // {img1, img0} 
    
        em.merge(shop); 
    } 
    

    내가 예외 이하 얻을 수는

    com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '5458-98711' for key 'uniqShopAndImage' 
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
        at java.lang.reflect.Constructor.newInstance(Constructor.java:408) 
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) 
        at com.mysql.jdbc.Util.getInstance(Util.java:386) 
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039) 
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609) 
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541) 
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002) 
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163) 
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624) 
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127) 
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2427) 
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2345) 
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2330) 
        at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
        at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:187) 
        ... 76 more 
    

    나는 것이 가능하다는 것을 알고있다 shop //shop.getImages(). clear()

  2. em.flush()
  3. shop.setImages (newImages); 나는이 솔루션을 좋아하지 않아

그러나

  • 때 em.merge (상점). 최대 절전 모드 4를 JPA Provider, MySQL DB로 사용합니다. 답변 해 주셔서 감사합니다.

  • 답변

    1

    MySQL은 연기 가능한 제약 조건 검사를 지원하지 않기 때문에 문제가 발생합니다. 단일 SQL 문을 실행하는 동안이 아니라 DB 트랜잭션을 커밋하는 동안 검사 제약 조건을 의미합니다. 자세한 대답은 here입니다. 내 문제에 대한

    ,

    show.setImages(Lists.newArrayList()); 
    entityManager.flush(); 
    

    그것을 해결할 수있다하지만 난 여전히이 솔루션을 좋아하지 않는다.