hibernate 대량 조작 실례 상세 설명

본고는 hibernate의 대량 조작 방법을 실례로 서술하였다.다음과 같이 여러분에게 참고할 수 있도록 공유합니다.
Hibernate의 대량 처리
Hibernate는 완전히 대상을 대상으로 하는 방식으로 데이터베이스를 조작합니다. 프로그램에서 대상을 대상으로 하는 방식으로 지속적인 대상을 조작할 때 데이터베이스에 대한 조작으로 자동으로 변환됩니다.예를 들어 Session의 delete () 방법을 호출하여 지구화 대상을 삭제하면 Hibernate는 해당하는 데이터 기록을 삭제하는 것을 책임진다.지속화 대상의 set 방법을 실행할 때, Hibernate는 자동으로 대응하는 업데이트 방법으로 전환하여 데이터베이스에 대응하는 기록을 수정합니다.
문제는 100 000 기록을 동시에 업데이트해야 한다면 100 000 기록을 하나씩 불러오고 순서대로 set 방법을 사용해야 하는 것이 아니냐는 것이다. 이렇게 하면 번거로울 뿐만 아니라 데이터 접근의 성능도 매우 나쁘다.이런 대량 처리 장면에 대해 Hibernate는 대량 처리 솔루션을 제공했다. 다음은 대량 삽입, 대량 업데이트와 대량 삭제 세 가지 측면에서 이런 대량 처리 상황에 어떻게 대처하는지 소개한다.
1 대량 삽입
데이터베이스에 100 000개의 레코드를 삽입해야 하는 경우 일반적으로 Hibernate는 다음과 같은 방법을 사용할 수 있습니다.

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
 User u = new User (.....);
 session.save(customer);
}
tx.commit();
session.close();

그러나 이 프로그램이 실행됨에 따라 언젠가는 실행에 실패하고 Out OfMemory Exception (메모리 넘침 이상) 을 던집니다.이것은 Hibernate의 Session이 반드시 선택한 1급 캐시를 가지고 있기 때문에 모든 사용자 실례가 Session 등급의 캐시 구역에서 캐시를 진행하기 때문입니다.
이 문제를 해결하기 위해서는 세션 캐시의 데이터를 데이터베이스에 갱신하는 것이 아니라 세션 레벨에서 캐시하는 것이 매우 간단한 사고방식이 있다.User 실례를 저장할 때마다 누적기가 1 증가하는 것을 고려할 수 있습니다.누적 값에 따라 Session 캐시의 데이터를 데이터베이스에 불러올 필요가 있는지 여부를 결정합니다.
다음은 사용자 인스턴스 100 000개를 추가하는 코드 세그먼트입니다.

private void testUser()throws Exception
{
 // Session
 Session session = HibernateUtil.currentSession();
 // 
 Transaction tx = session.beginTransaction();
 // 100 000 , 100 000 
 for (int i = 0 ; i < 1000000 ; i++ )
 {
  // User 
  User u1 = new User();
  u1.setName("xxxxx" + i);
  u1.setAge(i);
  u1.setNationality("china");
  // Session User 
  session.save(u1);
  // 20 , Session , Session 
  if (i % 20 == 0)
  {
   session.flush();
   session.clear();
   tx.commit();
   tx = session.beginTransaction();
  }
 }
 // 
 tx.commit();
 // 
 HibernateUtil.closeSession();
}

위 코드에서 i%20 == 0일 때 세션에 있는 캐시 데이터를 데이터베이스에 수동으로 기록하고 업무를 수동으로 제출합니다.만약 사무를 제출하지 않는다면 데이터는 여전히 사무처에 캐시되어 데이터베이스에 들어가지 않고 메모리가 넘치는 이상을 일으킬 것이다.
이것은 Session 레벨 캐시에 대한 처리이며, 다음 설정을 통해 SessionFactory의 2 레벨 캐시를 닫아야 합니다.
hibernate.cache.use_second_level_cache false
참고: Session 레벨의 캐시를 수동으로 비우는 것 외에 SessionFactory 레벨의 2단계 캐시를 닫는 것이 좋습니다.그렇지 않으면 Session 레벨의 캐시를 수동으로 비워도 SessionFactory 레벨에 캐시가 있기 때문에 이상이 발생할 수 있습니다.
2 대량 업데이트
위에서 소개한 방법은 대량으로 데이터를 업데이트하는 데도 적용된다. 만약에 여러 줄의 데이터를 되돌려야 한다면 scroll() 방법을 사용하여 서버 사이드 커서가 가져오는 성능 장점을 충분히 이용할 수 있다.다음은 대량 업데이트를 위한 코드 세션입니다.

private void testUser()throws Exception
{
 // Session
 Session session = HibernateUtil.currentSession();
 // 
 Transaction tx = session.beginTransaction();
 // User 
 ScrollableResults users = session.createQuery("from User")
  .setCacheMode(CacheMode.IGNORE)
  .scroll(ScrollMode.FORWARD_ONLY);
 int count=0;
 // User 
 while ( users.next() )
 {
  User u = (User) users.get(0);
  u.setName(" " + count);
  // count 20 , Session flush 
  if ( ++count % 20 == 0 )
  {
   session.flush();
   session.clear();
  }
 }
 tx.commit();
 HibernateUtil.closeSession();
}

이런 방식을 통해 대량 업데이트를 실행할 수 있지만 효과가 매우 좋지 않다.실행 효율이 높지 않을 뿐만 아니라 데이터 조회를 먼저 실행한 다음에 데이터 업데이트를 실행해야 한다. 또한 이런 업데이트는 한 줄씩 업데이트될 것이다. 즉, 한 줄의 기록을 업데이트할 때마다 업데이트 문구를 실행해야 하기 때문에 성능이 매우 떨어진다.
이러한 상황을 피하기 위해 Hibernate는 SQL의 대량 업데이트와 대량 삭제와 유사한 HQL 문법을 제공합니다.
3 SQL 스타일의 대량 업데이트/제거
Hibernate에서 제공하는 HQL 문장도 대량의 UPDATE와 DELETE 문법을 지원합니다.
대량 UPDATE 및 DELETE 문장의 구문 형식은 다음과 같습니다.

UPDATE | DELETE FROM? ClassName [WHERE WHERE_CONDITIONS]
위의 구문 형식에 관해서는 다음과 같은 네 가지 주의할 점이 있다.
● FROM 자문에서 FROM 키워드는 선택 사항입니다.FROM 키워드를 전혀 쓰지 않아도 됩니다.
● FROM 자구에는 하나의 클래스 이름만 있을 수 있으며, 이 클래스에는 별명이 있을 수 없습니다.
● 대량 HQL 문장에서는 연결을 사용할 수 없으며, 현식이나 은식이면 안 된다.그러나 WHERE 자문에서 하위 질의를 사용할 수 있습니다.
● 전체 WHERE 자구는 선택 사항입니다.
사용자 클래스 실례의name 속성을 대량으로 변경해야 한다고 가정하면 다음과 같은 코드 세션으로 완성할 수 있습니다.

private void testUser()throws Exception
{
 // Session
 Session session = HibernateUtil.currentSession();
 // 
 Transaction tx = session.beginTransaction();
 // HQL 
 String hqlUpdate = "update User set name = :newName";
 // 
 int updatedEntities = session.createQuery( hqlUpdate )
       .setString( "newName", " " )
       .executeUpdate();
 // 
 tx.commit();
 HibernateUtil.closeSession();
}

위 코드에서 알 수 있듯이 이런 문법은 PreparedStatement의executeUpdate 문법과 매우 유사하다.실제로 HQL의 이런 대량 업데이트는 SQL 문법의 UPDATE 문구를 직접 참고한 것이다.
참고: 이러한 대량 업데이트 구문을 사용할 때 일반적으로 SQL의 UPDATE 문구를 한 번만 실행하면 모든 조건 레코드 업데이트를 완료할 수 있습니다.그러나 여러 개의 UPDATE 문장을 실행해야 할 수도 있습니다. 이것은 계승 맵 등 특수한 상황이 있기 때문입니다. 예를 들어 Person 실례가 있고 Customer의 하위 클래스 실례가 있기 때문입니다.Person 인스턴스를 대량 업데이트할 때도 Customer 인스턴스를 업데이트해야 합니다.joined-subclass나 union-subclass 맵을 사용하면 Person과 Customer 실례가 다른 테이블에 저장되기 때문에 여러 개의 UPDATE 문장이 필요할 수 있습니다.
Query를 사용하는 HQL DELETE를 실행합니다.executeUpdate () 메서드, 아래에 기록된 모든 코드 세그먼트를 한 번에 삭제합니다.

private void testUser()throws Exception
{
 // Session 
 Session session = HibernateUtil.currentSession();
 // 
 Transaction tx = session.beginTransaction();
 // HQL 
 String hqlUpdate = "delete User";
 // 
 int updatedEntities = session.createQuery( hqlUpdate )
       .executeUpdate();
 // 
 tx.commit();
 // Session
 HibernateUtil.closeSession();
}

Query.executeUpdate () 방법은 이 작업의 영향을 받는 기록 수량인 정형 값을 되돌려줍니다.실제로 Hibernate의 기본 작업은 JDBC를 통해 이루어졌다.따라서 대량의 UPDATE나 DELETE 작업이 여러 개의 UPDATE 또는 DELETE 문장으로 변환되면 이 방법은 마지막 SQL 문장에 영향을 주는 기록 줄 수를 되돌려줍니다.
본고에서 기술한 바와 같이 Hibernate 프레임워크를 바탕으로 하는 자바 프로그램 설계에 도움이 되기를 바랍니다.

좋은 웹페이지 즐겨찾기