EclipseLink のキャッシュの中身を表示するサンプル

EclipseLink で L2 レベルのキャッシュ(Persistence Unit Cache という言うみたいです。persistence unit 単位のキャッシュですね)の中身を表示するサンプルです。EclipseLink では JpaCache というインタフェースが用意されていて、こいつがキャッシュの内容を表示する API を提供してくれている感じです。JpaCache の取得方法は EntityManagerFactory#getCache() で取れます。

・EclipseLink/Examples/JPA/Caching - Eclipsepedia
https://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching

・JpaCache (EclipseLink 2.1.2, build 'v20101206-r8635' API Reference)
http://www.eclipse.org/eclipselink/api/2.1/org/eclipse/persistence/jpa/JpaCache.html

以下がサンプル。いろいろ余計な処理がありますが、キャッシュを表示しているのは printCache() になります。

■ Main.java

package com.sample;

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

import org.eclipse.persistence.jpa.JpaCache;

import com.sample.entity.Test;

public class Main {

	private static final String PERSISTENCE_UNIT_NAME = "test";
	private static EntityManager em;

	public static void main(String[] args) {
		findTest(1);
		findTest(2);
		printCache();
		
		findTest(3);
		printCache();
	}

	public static void persistTest(int id, String name) {
		Test t = new Test();
		t.setId(id);
		t.setName(name);

		EntityManager em = getEntityManager();
		em.getTransaction().begin();
		em.persist(t);
		em.getTransaction().commit();
		em.close();
	}

	public static void findTest(int id) {
		EntityManager em = getEntityManager();
		Test t = em.find(Test.class, id);
		System.out.println("findTest() : " + t);
	}

	public static void printCache() {
		JpaCache cache = (JpaCache)em.getEntityManagerFactory().getCache();
		//System.out.println(cache);
		cache.print();
	}
	
	public static EntityManager getEntityManager() {
		if (em == null) {
			EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
			em = factory.createEntityManager();
		}
		return em;
	}

}


実行すると以下の感じ。★をつけた箇所が JpaCache#print() の出力です。find で Test のエンティティを取得するとキャッシュにのっていることが確認できますね。次に同じエンティティを取得する際は実際に DB には接続せずにキャッシュから取得されるはずです(ここはちゃんと確認はしてません)。

■ 実行結果

[EL Info]: 2016-12-29 16:59:07.952--ServerSession(1589931229)--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b
[EL Info]: connection: 2016-12-29 16:59:08.082--ServerSession(1589931229)--file:/C:/devspace/workspace45/EclipseLinkSample/target/classes/_test login successful
findTest() : 1:name1
findTest() : 2:name2
[EL Severe]: cache: 2016-12-29 16:59:08.156--ServerSession(1589931229)-- ★
SoftCacheWeakIdentityMap for: Test ★
Key: 1	Identity Hash Code: 382044126	Object: 1:name1 ★
Key: 2	Identity Hash Code: 1289454852	Object: 2:name2 ★
2 elements ★
findTest() : 3:name3
[EL Severe]: cache: 2016-12-29 16:59:08.16--ServerSession(1589931229)-- ★
SoftCacheWeakIdentityMap for: Test ★
Key: 1	Identity Hash Code: 382044126	Object: 1:name1 ★
Key: 2	Identity Hash Code: 1289454852	Object: 2:name2 ★
Key: 3	Identity Hash Code: 551421413	Object: 3:name3 ★
3 elements ★


取れてくる値がおかしいなり、なんとなくキャッシュまわりではまった際は、一度、上記の方法でキャッシュの中身を見てみるといいかもしれません。


以下、一応、Entity Class、persistence.xml をのせておきます。

■ Test.java(Entity Class)

package com.sample.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Test {
	
	public Test() {}
	
	@Id
	@Column(name="id")
	private int id;
	
	@Column(name="name")
	private String name;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public String toString() {
		return id + ":" + name;
	}
}

■ persistence.xml

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
        version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
        <persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
                <class>com.sample.entity.Test</class>
 <properties>
  <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
  <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/postgres" />
  <property name="javax.persistence.jdbc.user" value="postgres" />
  <property name="javax.persistence.jdbc.password" value="postgres" />

  <!-- EclipseLink should create the database schema automatically -->
  <property name="eclipselink.ddl-generation" value="create-tables" />
  <property name="eclipselink.ddl-generation.output-mode" value="database" />
 </properties>

        </persistence-unit>
</persistence>


簡単ですが、以上になります。

[検証環境]
Windows 10
Java SE 8 Update 92
EclipseLink 2.5.0
PostgreSQL JDBC Driver 9.4.1212
PostgreSQL 9.5