Cascadeのメモ

CascadeType.PERSIST, CascadeType.REMOVEの確認

MovieのCascadeTypeを次のように変更し、動作確認をしてみた。

    		cascade=CascadeType.ALL, 
    		↓
    		cascade={CascadeType.PERSIST, CascadeType.MERGE}, 


CascadeExSample.class

package sample;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class CascadeExample {
	
	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hibernate");
		EntityManager em = emf.createEntityManager();
		
	    final EntityTransaction tx = em.getTransaction();
	    tx.begin();

	    Actor brad = new Actor("Brad Pitt");
	    Actor orlando = new Actor("Orlando Bloom");
	    
	    Movie troy = new Movie("Troy");
	    
	    troy.addActor(brad);
	    troy.addActor(orlando);

	    // Movie で CascadeType.PERSIST または CascadeType.ALL を定義している場合、
	    // Actor も登録される
	    em.persist(troy);
	    
	    // Movie で CascadeType.REMOVE または CascadeType.ALL を定義していない為、
	    // Movieのみ削除される
	    em.remove(troy);
	    
		tx.commit();
		
		em.close();
		emf.close();
	}

}
実行結果
  • cascade=CascadeType.ALL の場合

SELECT * FROM ACTOR ;

ID NAME

SELECT * FROM MOVIE_ACTOR ;

MOVIE_ID ACTOR_ID

SELECT * FROM MOVIE;

ID NAME
  • cascade={CascadeType.PERSIST, CascadeType.MERGE} の場合

SELECT * FROM ACTOR ;

ID NAME
67 Orlando Bloom
68 Brad Pitt

SELECT * FROM MOVIE_ACTOR ;

MOVIE_ID ACTOR_ID

SELECT * FROM MOVIE;

ID NAME

CascadeType.REFRESHの確認

CascadeType.MERGE は、まぁ CascadeType.PERSIST と似たようなもんだろうということで、
CascadeType.REFRESH について少し動作を確認してみる。

CascadeType.REFRESH と fetch=FetchType.LAZY を併用した場合に EntityManager.find() では関連エンティティが取得されず、 EntityManager.refresh() を呼び出した場合のみ関連エンティティが取得されることを確認する。

CascadeRefreshExample.class

package sample;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class CascadeRefreshExample {
	
	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hibernate");
		EntityManager em = emf.createEntityManager();
		
	    final EntityTransaction tx = em.getTransaction();
	    tx.begin();

	    Actor brad = new Actor("Brad Pitt");
	    Actor orlando = new Actor("Orlando Bloom");
	    
	    Movie troy = new Movie("Troy");
	    
	    troy.addActor(brad);
	    troy.addActor(orlando);
	    
	    em.persist(troy);

	    
		tx.commit();
		
		// EntityManagerをclose
		em.close();
		
		// EntityManagerを再取得
		em = emf.createEntityManager();
		
		// fetch=FetchType.LAZY なのでMovieは取得しない
	    System.out.println("####################################### find");
	    Actor brad2 = em.find(Actor.class, brad.getId());
	    System.out.println("############################################");
	    
	    System.out.println("#################################### refresh");
	    // Actor で CascadeType.REFRESH または CascadeType.ALL を定義している為、
	    // Movieも取得される
	    em.refresh(brad2);
	    System.out.println("############################################");

	    em.close();
		emf.close();
	}

}
実行結果

どうやら期待通りに動いてくれたらしい。

コンソールログ

####################################### find
Hibernate: 
    select
        actor0_.id as id0_0_,
        actor0_.name as name0_0_ 
    from
        Actor actor0_ 
    where
        actor0_.id=?
############################################
#################################### refresh
Hibernate: 
    select
        actor0_.id as id0_1_,
        actor0_.name as name0_1_,
        movies1_.actor_id as actor2_3_,
        movie2_.id as movie1_3_,
        movie2_.id as id1_0_,
        movie2_.name as name1_0_ 
    from
        Actor actor0_ 
    left outer join
        movie_actor movies1_ 
            on actor0_.id=movies1_.actor_id 
    left outer join
        Movie movie2_ 
            on movies1_.movie_id=movie2_.id 
    where
        actor0_.id=?
############################################