ToplinkのLazy Loading その2

さっきのhttp://d.hatena.ne.jp/taedium/20060503#p1をもう少し詳しく見てみます。

DDL。CreditCard にカラム追加しました。

drop table user;
drop table creditcard;
drop table billingdetails;

create table BillingDetails (
    ID INTEGER PRIMARY KEY,
    DTYPE VARCHAR(31),
    NUMBER VARCHAR(10)
);

create table CreditCard (
    ID INTEGER PRIMARY KEY,
    EXPYEAR VARCHAR(4),
    EXPMONTH VARCHAR(2)
);

create table User (
    ID INTEGER PRIMARY KEY,
    BILLINGDETAILS_ID INTEGER NOT NULL,
    FOREIGN KEY (BILLINGDETAILS_ID) REFERENCES BILLINGDETAILS (ID)  
);

insert into BillingDetails values(1, 'CreditCard', '2010')
insert into CreditCard values(1, '2008', '08')
insert into User values(1,1)

UserクラスとBillingDetails には変更加えません。

CreditCard クラス。カラムに対応したフィールド追加しました。

@Entity
public class CreditCard extends BillingDetails {
	
	private String expYear;
	
	private String expMonth;
	
	public String toString() {
		return "expYear=" + expYear + ", expMonth=" + expMonth;
	}
}

実行クラス。文字を出力したり、userインスタンスのFieldやMethodを調べたりしてます

public class Client {

	private static EntityManagerFactory emf;

	private static EntityManager em;

	public static void main(String[] args) throws Exception {
		emf = Persistence.createEntityManagerFactory("emf");
		createTransactionalEntityManager();

		System.out.println("before em.find(User.class, 1)");
		User user = em.find(User.class, 1);
		System.out.println("after em.find(User.class, 1)");

		System.out.println("before invoking user.getBillingDetails()");
		BillingDetails bd = user.getBillingDetails();
		System.out.println("after invoking user.getBillingDetails()");
		System.out.println("bd : " + bd);

		for (Class current = user.getClass(); current != null
				&& current != Object.class; current = current.getSuperclass()) {
			System.out.println("detect " + current + " fields");
			for (Field field : current.getDeclaredFields()) {
				System.out.println(current + "." + field.getName());
			}
			System.out.println("detect " + current + " methods");
			for (Method method : current.getDeclaredMethods()) {
				System.out.println(current + "." + method.getName());
			}
		}

		closeTransactionalEntityManager();
	}

	private static void createTransactionalEntityManager() {
		em = emf.createEntityManager();
		em.getTransaction().begin();
	}

	private static void closeTransactionalEntityManager() {
		em.getTransaction().commit();
		em.close();
	}

}

実行結果(整形してます。SQLはログ出力されたものです。)

before em.find(User.class, 1)
  SELECT ID, BILLINGDETAILS_ID FROM USER WHERE (ID = ?)
after em.find(User.class, 1)

before invoking user.getBillingDetails()
  SELECT DISTINCT DTYPE FROM BILLINGDETAILS WHERE (ID = ?)
  SELECT t0.ID, t0.DTYPE, t0.NUMBER, t1.ID, t1.EXPYEAR, t1.EXPMONTH FROM BILLINGDETAILS t0, CREDITCARD t1 WHERE ((t0.ID = ?) AND ((t1.ID = t0.ID) AND (t0.DTYPE = ?)))
after invoking user.getBillingDetails()

bd : expYear=2008, expMonth=08

detect class entity.User fields
class entity.User.id
class entity.User.billingDetails
class entity.User._toplink_billingDetails_vh

detect class entity.User methods
class entity.User.setId
class entity.User.getBillingDetails
class entity.User.setBillingDetails
class entity.User.weavedValueHolders
class entity.User._toplink_getbillingDetails
class entity.User._toplink_setbillingDetails
class entity.User._toplink_getbillingDetails_vh
class entity.User._toplink_setbillingDetails_vh
class entity.User.getId

なにやら怪しげな?フィールドやメソッドが追加されてました。_vhっていうサフィックスはなんでしょう。
でかけなければいけないので、とりあえずここまで。考察はid:koichikさんがしてくれるかも。