ã¡ã¢ãªãé¼è¿«ãããã«JPAã§å¤§éãã¼ã¿ãåå¾ããæ¹æ³
JPAï¼Java Persistence APIï¼ã¯ããã¼ã¿ãã¼ã¹ããåå¾ãããã¼ã¿ãã¡ã¢ãªä¸ã«ä¿æãã仿§ã«ãªã£ã¦ããã
ãã®ãããä¸ç¨æã«å¤§éã®ãã¼ã¿ãåå¾ããã¨ãã¡ã¢ãªå®¹éãå§è¿«ãã¦ãã¾ããææªã®å ´åã¯OutOfMemoryError
ãèµ·ããå¯è½æ§ãããã
æ¬ç¨¿ã§ã¯ãJPAã®æ¨æºæ©è½ããã³ãã¤ãã£ãæ©è½ã®ããããã«ã¤ãã¦ãã¡ã¢ãªä½¿ç¨éãæããªãã大éãã¼ã¿ãåå¾ããæ¹æ³ã¨ããã¤ãã£ãæ©è½ããã¾ãåä½ããªãå ´åã®åé¿çãç´¹ä»ããã
JPAã¯èªã¿è¾¼ãã ãã¼ã¿ã䏿¬¡ãã£ãã·ã¥ã¨ãã¦ä¿æãã
JPAã¯ãèªã¿è¾¼ãã Entity
ãPersistenceContext
ï¼æ°¸ç¶åã³ã³ããã¹ãï¼ã¨å¼ã¶é åã§ç®¡çããã
ããã«æ ¼ç´ãããç¶æ
ã䏿¬¡ãã£ãã·ã¥ã¨å¼ã³ã䏿¬¡ãã£ãã·ã¥ãããEntity
ãManagedãªç¶æ
ï¼JPAã«ç®¡çãããç¶æ
ï¼ã¨å¼ã¶ï¼ãªããäºæ¬¡ãã£ãã·ã¥ãããã岿ããï¼ã
PersistenceContext
ã¯ããã¼ã«Entity
ã®IDããå¤ã«Entity
ãã»ããããMap<String, Object>
ã®ãããªãã¼ã¿æ§é ã§ããã
import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; ... public class ProductService { @PersistenceContext private EntityManager entityManager; public void loadAll() { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<ProductEntity> criteriaQuery = builder.createQuery(ProductEntity.class); Query query = entityManager.createQuery(criteriaQuery); List<ProductEntity> products = query.getResultList(); for (ProductEntity product : products) { LOG.debug("ProductEntity: " + entity); } } }
ä¸è¨ã®ã³ã¼ããå®è¡ããã¨ãQuery
ãªãã¸ã§ã¯ãã®getResultList
ãå¼ã³åºããæç¹ã§ããã¼ã¿ãã¼ã¹ã«æ ¼ç´ããã¦ããå
¨ã¬ã³ã¼ããã¡ã¢ãªã«å±éããã¦ãã¾ããã¬ã³ã¼ãä»¶æ°ãå°ãªããã°åé¡ãªããã大éã®ã¬ã³ã¼ããæ ¼ç´ããã¦ãããã¼ãã«ã®å ´åã«ã¯ãã¡ã¢ãªã大ããæ¶è²»ãã¦ãã¾ãã
䏿¬¡ãã£ãã·ã¥ãã¯ãªã¢ããªããæ®µéçã«ã¯ã¨ãªã¼ãå®è¡ãã
ãã®åé¡ã«å¯¾å¦ããæ¹æ³ã®ä¸ã¤ã¨ãã¦ã段éçã«ã¯ã¨ãªã¼ãå®è¡ããæ¹æ³ãããã
次ã®ããã«ãä»¶æ°ãçµã£ã¦ã¯ã¨ãªã¼ãå®è¡ãã宿çã«EntityManager#clear
ãå¼ã³åºãã°ãPersistenceContext
ã«æ ¼ç´ããã䏿¬¡ãã£ãã·ã¥ãã¯ãªã¢ã§ããã
public class ProductService { @PersistenceContext private EntityManager entityManager; public void loadAll() { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<ProductEntity> criteriaQuery = builder.createQuery(ProductEntity.class); int offset = 0; Query query = entityManager.createQuery(criteriaQuery); List<ProductEntity> products; // 1000ä»¶ãã¤ã«ä»¶æ°ãçµã while ((products = query.setFirstResult(offset) .setMaxResults(1000) .getResultList()) .size() > 0) { for (ProductEntity product : products) { LOG.debug("ProductEntity: " + entity); } entityManager.clear(); // 䏿¬¡ãã£ãã·ã¥ã®ã¯ãªã¢ offset += products.size(); } }
ä¸è¨ã®ã³ã¼ãã§ã¯ãã¯ã¨ãªã¼å®è¡æã«Query
ãªãã¸ã§ã¯ãã«å¯¾ãã¦ãsetFirstResult()
ã¨setMaxResults()
ãå¼ã³åºããã¨ã§ã1åã«èªã¿è¾¼ããã¼ã¿éãå¶å¾¡ãã¦ãããããã¦ãèªã¿è¾¼ãã ãã¼ã¿ã®å¦çãçµãã£ããã¨ã§EntytManager#clear
ãå¼ã³åºããã¨ã§ã䏿¬¡ãã£ãã·ã¥ãã¯ãªã¢ãã¦ããã
ãã¤ãã£ãæ©è½ãå©ç¨ãã¦å ¨ä»¶åå¾ãå®è¡ãã
ä¸ã®æ¹æ³ã§ã¯ãã³ã¼ããç
©ããããªããã¨ã«å ãã¦ãæå®ããä»¶æ°åã ãã®ã¡ã¢ãªã使ã£ã¦ãã¾ãã
ãããé¿ããæ¹æ³ã¨ãã¦ã¯ãJPAã®ã¤ã³ã¿ãã§ã¼ã¹ã使ããã«ãå®è£
ã©ã¤ãã©ãªï¼Hibernateãªã©ï¼ã®ãã¤ãã£ãæ©è½ãå©ç¨ããæ¹æ³ãããã
Hibernateã®ä»£æ¿æ©è½ã¯ãScrollableResults
ã§ããã
JPAã¨ScrollableResults
ã®éãã¯æ¬¡ã®éãã
JPA
ãã¼ã¿ã®å徿ã«å ¨ã¦ã®ã¬ã³ã¼ããèªã¿è¾¼ã¾ãã䏿¬¡ãã£ãã·ã¥ã«æ ¼ç´ãããScrollableResults
ScrollableResults#get
ãå¼ã³åºãã¦Entity
ãåå¾ããã¿ã¤ãã³ã°ã§å¯¾è±¡ãã¼ã¿ãèªã¿è¾¼ã¾ãã䏿¬¡ãã£ãã·ã¥ã«æ ¼ç´ãããã
ScrollableResults
ã¯ãjava.sql.ResultSet
ã¨ä¼¼ã¦ãããããã£ãã·ã¥ã®æ±ãã¯ç°ãªããããªãã¡ScrollableResults
ã®å ´åã¯ãJPAã¨åæ§ã«Entity
ãåå¾ãããã³ã«PersistenceContext
ã«ä¸æ¬¡ãã£ãã·ã¥ã¨ãã¦æ ¼ç´ããã¦ãã¾ãããã®ãããå
ã»ã©ã®ããã«ãå¦çæ¸ã¿ã®Entity
ã¯EntityManager#clear
ãå¼ã³åºãã¦ã¯ãªã¢ããå¿
è¦ãããã
以ä¸ã«ScrollableResults
ã使ç¨ãã¦1000ä»¶æ¯ã«ä¸æ¬¡ãã£ãã·ã¥ãã¯ãªã¢ããå¦çã³ã¼ããç´¹ä»ããã
import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.hibernate.ScrollableResults; ... public class ProductService { @PersistenceContext private EntityManager entityManager; // 大éãã¼ã¿ãåå¾ããæ¤è¨¼ã¡ã½ãã public void loadAll() { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<ProductEntity> criteriaQuery = builder.createQuery(ProductEntity.class); Query query = entityManager.createQuery(criteriaQuery); org.hibernate.Query hibernateQuery = query.unwrap(org.hibernate.Query.class); ScrollableResults results = hibernateQuery.scroll(); int count = 0; while (results.next()) { count++; ProductEntity entity = (ProductEntity) results.get(0); LOG.debug("ProductEntity: " + entity); if (count % 1000 == 0) { // 1000ä»¶æ¯ã«è§£æ¾ entityManager.clear(); } } results.close(); } }
ãã¤ãã£ãæ©è½ããã¾ãåä½ããªãå ´åã®åé¿ç
ãã®ã³ã¼ãã¯åºæ¬çã«æ£ããåä½ããã¯ãã ããæã
ãé¢ãã£ãããã·ã¹ãã ã§ã¯æ£ããåä½ããªãã£ãã
ããªãã¡ãEntityManager#clear()
ãå¼ã³åºãã¦ã䏿¬¡ãã£ãã·ã¥ãã¯ãªã¢ã§ãããOutOfMemoryError
ãçºçããã
ãã®åé¡ãçºçããæ¡ä»¶ã¯æ¬¡ã®éãã
- ã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã¼ï¼WebSphere Application Server 8.0.0.5
- transaction-typeï¼JTA
- 宣è¨çãã©ã³ã¶ã¯ã·ã§ã³ï¼@Transactionalï¼ï¼æå®ããªã
ç°¡åãªåé¿çã¯ã@Transactionalãæå®ãããã¨ã§ããã
ãããã大éãã¼ã¿ãåç
§ããã¢ããªã±ã¼ã·ã§ã³ã«å¯¾ãã¦ãã©ã³ã¶ã¯ã·ã§ã³ãæå®ããã¨ãã¿ã¤ã ã¢ã¦ãæã®ä¾å¤ãã³ããªã³ã°ã«ã¤ãã¦èæ
®ããå¿
è¦ãåºã¦ããã宿ã«ã¿ã¤ã ã¢ã¦ãæéãå»¶ã°ãã°ãæ¬æ¥ã®ãã©ã³ã¶ã¯ã·ã§ã³å¦çã«ãå½±é¿ããã ããã
䏿¬¡ãã£ãã·ã¥ãå©ç¨ããªãScrollableResults
ã®å©ç¨
ãã®åé¡ã®åé¿çã¨ãã¦ã䏿¬¡ãã£ãã·ã¥ããªãScrollableResults
ãçæããæ¹æ³ãããã
ãã®ScrollableResults
ã¯ãorg.hibernate.Session
ã®ä»£ããã«ãorg.hibernate.StatelessSession
ãå©ç¨ãããã¨ã§åå¾ã§ããã
å®è£
ä¾ã¯æ¬¡ã®éãã
import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.hibernate.ScrollableResults; ... public class ProductService { @PersistenceContext private EntityManager entityManager; // 大éãã¼ã¿ãåå¾ããæ¤è¨¼ã¡ã½ãã public void loadAll() { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<ProductEntity> criteriaQuery = builder.createQuery(ProductEntity.class); // Queryã§ã¯ãªãTypedQueryãä½¿ç¨ TypedQuery<MyEntity> typedQuery = entityManager.createQuery(criteriaQuery); // Hibernateã®APIã使ç¨ããããã«ãã¦ã³ãã£ã¹ã AbstractQueryImpl queryImpl = typedQuery .unwrap(AbstractQueryImpl.class); org.hibernate.ejb.AbstractQueryImpl<T> ejbQuery = typedQuery .unwrap(org.hibernate.ejb.AbstractQueryImpl.class); // Queryæååã®åå¾ String namedSql = queryImpl.getQueryString(); // Hibernateã®StatelessSessionãåå¾ // è£è¶³ //////////////////////////////////////////// // StatelessSession ã¯é¢é£ããæ°¸ç¶ã³ã³ããã¹ããæã // ãã䏿¬¡ãã£ãã·ã¥ãå®è£ ãã¦ããªãã // (JPA)PersistenceContextã«Entityãªãã¸ã§ã¯ãããã£ã // ã·ã¥ããªãDetachedãªEntityãªã®ã§ã // EntityManager#clear()ãå¼ã¶å¿ è¦ããªãã // ã¤ã¾ããEntityãªãã¸ã§ã¯ããã¡ã¢ãªã«èç©ãããªãã //////////////////////////////////////////////////// StatelessSession statelessSession = ((Session)em.getDelegate()) .getSessionFactory().openStatelessSession(); // StatelessSessionã§Queryãåçæ org.hibernate.Query hibernateQuery = statelessSession .createQuery(namedSql); // ãã©ã¡ã¿ã®ãã¤ã³ã for (String name : (Set<String>) queryImpl.getParameterMetadata() .getNamedParameterNames()) { Object value = ejbQuery.getParameterValue(name); hibernateQuery.setParameter(name, value); } // #scroll()ãå®è¡ãScrollablrResultsãåå¾ããã // 次ã®è¨å®ãã¡ã¢ãªä½¿ç¨éã¨å¿çæéãè¯ãã£ãã®ã§æ¡ç¨ãã¦ããã ScrollableResults results = hibernateQuery.setReadOnly(true) .setCacheable(false).scroll(ScrollMode.FORWARD_ONLY); while (results.next()) { ProductEntity entity = (ProductEntity) results.get(0); LOG.debug("ProductEntity: " + entity); // ã¡ã¢ãªã®è§£æ¾ãä¸è¦ } results.close(); statelessSession.close(); } }
ãã®ä»çµã¿ãå©ç¨ããã°ã䏿¬¡ãã£ãã·ã¥ã®ã¯ãªã¢å¦çãããã©ã³ã¶ã¯ã·ã§ã³å®£è¨ã®èæ ®ã¯ä¸è¦ã«ãªãã
[髿© 忍¹]