행복한 아빠
Spring과 Hibernate에서 Blob Object 처리하기 본문
단지 필드를 byte[] 타입으로 저장하고 Lob이라고 지정하면 끝이 납니다. 아래처럼 말이죠.
... @Lob @Column(name="PHOTO") private byte[] photo[]; ....
뭐가 문제일까?
파일내용을 DB로 넣기 위해 객체에서 위 방법대로 byte 배열로 모두 가지고 있으면 운영 시 상당한 문제를 발생시킬 수 있습니다. 예를 들어 몇십 메가바이트의 파일을 업로드하기 위해 저 방법을 사용한다면 몇십 메가바이트의 파일 내용이 메모리에 그대로 올라가게 됩니다. (사실 몇십메가바이트 이상 쓰게 됩니다)
JVM은 한정된 메모리에서 동작하므로 이러한 방법은 애플리케이션 성능에 막대한 영향을 미칠 수 있습니다. 동시 사용자가 많을 경우 OutOfMemoryError 가 발생하는 상황을 만날수도 있습니다.
JVM은 가비지 컬렉션을 어떻게 하느냐 얼마나 하느냐에 따라 성능을 좌우하기도 합니다. 메모리 함부로 쓰지 마세요~
Hibernate에서 이러한 LOB 처리를 메모리에 올리는 방법이 아니라 스트림으로 처리하는 방법을 잘 정리한 블로그가 있어 정리해봅니다. 파일이나 입력스트림을 읽는 즉시 DB의 LOB에 스트림으로 바로 넣으니 메모리 사용이 없고 중간과정 없으니 속도도 훨씬 빠릅니다.
원문: http://turgaykivrak.wordpress.com/2008/06/06/blob-objects-with-spring-and-hibernate/
Spring과 Hibernate로 Blob 처리하기
당신은 스트림 객체들을 가지고 있습니다. 즉 파일들이죠. 그리고 이것을 hibernate와 spring을 이용하여 database에 넣고 싶습니다.
무엇보다도 먼저 파일내용(byte)만 저장하는 객체를 따로 만들라고 권장하고 싶습니다.
public class MyFileContent extends Entity { private InputStream content; MyFileContent () { } public MyFileContent(InputStream content) { this.content = content; } public InputStream getContent() { return content; } private void setContent(InputStream content) { this.content = content; } }
여기에서 상속받은 Entity 는 단지 id를 가지고 있는 base 클래스입니다. 뭐 id의 getter, setter도 있겠지요.
아래에 blob에 대한 hibernate 사용자 타입이 있습니다. (hibernate가 blob 처리를 아래 클래스로 하게 할 겁니다.)
import java.io.InputStream; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import org.hibernate.HibernateException; import org.springframework.jdbc.support.lob.LobCreator; import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.orm.hibernate3.support.AbstractLobType; public class BlobUserType extends AbstractLobType { public int[] sqlTypes() { return new int[] { Types.BLOB }; } public Class returnedClass() { return InputStream.class; } protected Object nullSafeGetInternal(ResultSet rs, String[] names, Object owner, LobHandler lobHandler) throws SQLException, HibernateException { return lobHandler.getBlobAsBinaryStream(rs, names[0]); } protected void nullSafeSetInternal(PreparedStatement ps, int index, Object value, LobCreator lobCreator) throws SQLException, HibernateException { if (value != null) { lobCreator.setBlobAsBinaryStream(ps, index, (InputStream) value, -1); } else { lobCreator.setBlobAsBytes(ps, index, null); } }
MyFileContent 클래스의 hibernate 매핑입니다.
HibernateContext.xml의 hiberation 설정입니다.
Oracle과 Websphere를 사용한다면 defaultLobHandler 대신 아래것을 사용해야 합니다. Oracle의 blob 객체는 좀 다르기 때문이죠.
마지막으로 사용해 봅시다.
InputStream inputStream = ...; MyFileContent fileContent = new StoredFile(inputStream); myRepository.save(fileContent );
테스트 하는 건 잊지 마세요 :)
'잡다한기록' 카테고리의 다른 글
가끔 사용하고 잊기 쉬운 Unix 명령 (0) | 2009.12.09 |
---|---|
JPA 에서 Blob 처리 (1) | 2009.12.03 |
Spring과 Hibernate에서 Blob Object 처리하기 (0) | 2009.12.02 |
AWK 초간단 사용법 (0) | 2009.12.01 |
JConsole로 JVM 상태 보기 (0) | 2009.11.30 |
개발에 필요한 MySQL 명령들 (0) | 2009.08.12 |