2016-04-12 17 views
0

テストの実行中にエラーが発生しました。私はSQLIntegrityConstraintViolationExceptionを取得します。一意キーまたは主キー制約でキー値が重複したためにステートメントが中止されました

Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL160412141534310' defined on 'CHARACTERS'. 

Characterクラスのコード

@Entity 
@Table(name = "CHARACTERS") 
@NamedQueries({ 
@NamedQuery(name = Character.FIND_ALL, query = "SELECT c FROM Character c") 
}) 
public class Character implements Serializable { 

public static final String FIND_ALL = "Character.findAll"; 

private static final long serialVersionUID = 1L; 

@Id 
private int id; 

@Column(length = 50) 
private String name; 

public Character() { 
} 

public Character(int id, String name) { 
    this.id = id; 
    this.name = name; 
} 

public Character(String name) { 
    this.name = name; 
} 

/* Getter and setter below */ 

CharactersBeanクラス

@Stateful 
@TransactionAttribute(TransactionAttributeType.NEVER) 
public class CharactersBean implements Serializable { 

@PersistenceContext(type = PersistenceContextType.EXTENDED) 
EntityManager em; 

public void save(Character e) { 
    em.persist(e); 
} 

@TransactionAttribute(TransactionAttributeType.REQUIRED) 
public void commitChanges() { 

} 

public List<Character> get() { 
    return em.createNamedQuery(Character.FIND_ALL, Character.class).getResultList(); 
} 

テストクラス それはshould_update_characters_after_transaction_flushを実行すると、上記の例外がスローされます。

@RunWith(Arquillian.class) 
public class ExtendedPersistenceContextTest { 

@PersistenceContext 
EntityManager em; 

@EJB 
CharactersBean bean; 

@Deployment 
public static WebArchive deploy() { 
    return ShrinkWrap.create(WebArchive.class) 
      .addPackage("org.javaee7.jpa.extended.pc") 
      .addAsResource("META-INF/persistence.xml") 
      .addAsResource("META-INF/create.sql") 
      .addAsResource("META-INF/drop.sql") 
      .addAsResource("META-INF/load.sql"); 
} 

@Before 
public void setup() { 
    Character wil = new Character(8, "Wil Wheaton"); 
    bean.save(wil); 

    for (Character c : bean.get()) { 
     if ("Raj".equals(c.getName())) { 
      c.setName("Rajesh Ramayan"); 
      bean.save(c); 
     } 
    } 
} 

@Test 
@InSequence(1) 
public void should_not_persist_changes_without_transaction_flush() { 
    List<Character> characters = em.createNamedQuery(Character.FIND_ALL, Character.class).getResultList(); 
    Character raj = em.find(Character.class, 6); 

    assertThat(characters, hasSize(7)); 
    assertThat(raj.getName(), is(equalTo("Raj"))); 
} 

@Test 
@InSequence(2) 
public void should_update_characters_after_transaction_flush() { 
    //when 
    bean.commitChanges(); 

    //then 
    List<Character> characters = em.createNamedQuery(Character.FIND_ALL, Character.class).getResultList(); 
    Character rajesh = em.find(Character.class, 6); 
    Character wil = em.find(Character.class, 8); 

    assertThat(characters, hasSize(8)); 
    assertThat(rajesh.getName(), is(equalTo("Rajesh Ramayan"))); 
    assertThat(wil.getName(), is(equalTo("Wil Wheaton"))); 
} 

データはDerbyデータベースに入力してください。

INSERT INTO CHARACTERS("ID", "NAME") VALUES (1, 'Penny') 
INSERT INTO CHARACTERS("ID", "NAME") VALUES (2, 'Sheldon') 
INSERT INTO CHARACTERS("ID", "NAME") VALUES (3, 'Amy') 
INSERT INTO CHARACTERS("ID", "NAME") VALUES (4, 'Leonard') 
INSERT INTO CHARACTERS("ID", "NAME") VALUES (5, 'Bernadette') 
INSERT INTO CHARACTERS("ID", "NAME") VALUES (6, 'Raj') 
INSERT INTO CHARACTERS("ID", "NAME") VALUES (7, 'Howard') 

答えて

4

これはテストフレームワークの動作方法のJUnitに関連している: 特定のイベント時に実行されなければならないメソッドをマーキング5アノテーションの合計があります

  • @BeforeClass:この方法は、を実行しますいずれかのテストが実行される前に、一旦になる。
  • @Before:このメソッドは、呼び出されactualy試験方法の前に実行される、され、その各試験方法のための新しい
  • @Test:この方法は、後に実行されます。これは、実際の試験方法
  • @Afterあります各試験方法は、次のテスト
  • @AfterClassのためにクリーンアップするために、実行が終了:すべてのテストメソッドが終了した後、この方法では、オープンデータベース接続か何かを閉じるために、実行されます...

あなたのテストクラスでは、毎回新しいテストの前にウィルウィートン氏を存続させようとします。 これは初めて動作していますが、2回目にはエントリはすでに保持されています。まったく同じIDで永続化しようとすると、独自の制約に違反します。

@Before@BeforeClassアノテーションに置き換えると、エントリは1回だけ永続化されるか、データベースからエントリを削除する@Afterアノテーションのメソッドを追加するので、新しいものを挿入することができます。

さらに、テストが完了した後、テストによって挿入されたエントリのデータベースを削除することをお勧めします。あなたは簡単に @Afterまたは@AfterClass

敬具に

をアノテーション付きメソッドを使用してJ.Adam

ことを行うことができます
関連する問題