일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- jpa
- 역학
- 유닉스
- 코틀린
- 고전역학
- 리눅스
- 데이터베이스
- 자바암호
- write by GPT-4
- Database
- GPT-4's answer
- Java
- flet
- JVM
- 웹 크롤링
- spring data jpa
- oracle
- chatGPT's answer
- 자바
- python
- android
- 시스템
- 파이썬
- NIO
- 자바네트워크
- kotlin
- 인프라
- write by chatGPT
- 소프트웨어공학
- spring integration
- Today
- Total
기억을 지배하는 기록
객체 저장 : Storing Classes, Images and Other Large Objects 본문
객체 저장 : Storing Classes, Images and Other Large Objects
Andrew's Akashic Records 2018. 4. 7. 22:58만약 long raw, longvarbinary, 혹은 다른 유사한 타입이 데이터베이스에 제공된다면, 많은 데이터베이스는 바이너리 데이터를 열의 일부로 저장할 수 있다. 이들 필드는 2기가 바이트까지 수용할 수 있다. 이것은 여러분이 데이터를 바이너리 스트림이나 바이트 배열로 변환할 수 있다면, string이나 double과 같은 방법으로 데이터 베이스에 저장되고 추출될 수 있음을 의미한다.
이 기술은 이미지나 Java 객체를 저장하고 추출하는데 사용될 수 있다.
Storing and retrieving an image: 직렬화되었거나, 바이트 배열로 변환된 객체를 저장하는 것은 매우 쉽다. 불행하게도 java.awt.Image 는 Serializable 되지 않는다. 그러나, 다음 코드에서와 같이 이미지 데이터를 파일로 저장할 수 있고, 파일에 있는 정보를 데이터베이스 바이너리 필드에 바이트로 저장할 수 있다.
int itemnumber=400456;
File file = new File(itemnumber+".jpg");
FileInputStream fis = new FileInputStream(file);
PreparedStatement pstmt = con.prepareStatement(
"update auctionitems
set theimage=? where id= ?");
pstmt.setBinaryStream(1, fis, (int)file.length()):
pstmt.setInt(2, itemnumber);
pstmt.executeUpdate();
pstmt.close();
fis.close();
이미지를 추출하고 createImage 로 전달될 수 있는 바이트 배열로 생성하기 위해서는 아래와 같이 하라:
int itemnumber=400456;
byte[] imageBytes;
PreparedStatement pstmt = con.prepareStatement(
"select theimage from auctionitems where id= ?");
pstmt.setInt(1, itemnumber);
ResultSet rs=pstmt.executeQuery();
if(rs.next()) {
imageBytes = rs.getBytes(1);
}
pstmt.close();
rs.close();
Image auctionimage =
Toolkit.getDefaultToolkit().createImage(imageBytes);
Storing and retrieving an object: 클래스는 전의 예에서 이미지와 같은 방법으로 바이너리 데이터베이스 필드로 직렬화될 수 있다. RegistrationImpl 클래스는 클래스 선언에 implements Serializable를 추가함으로써 기본적인 직렬화를 지원하도록 수정될 수 있다.
다음, ByteArrayInputStream 이 JDBC 바이너리 스트림으로서 전달되도록 생성된다. ByteArrayInputStream을 생성하기 위해, RegistrationImpl 은 우선 RegistrationImpl.writeObject을 호출하는 ByteArrayInputStream 에 기반한 ObjectOutputStream 에 파이프(pipe)화된다(연결통로를 만듦). ByteArrayInputStream 은 바이트 배열로 변환되고, 그것은 ByteArrayInputStream 을 생성하는데 주로 사용된다. RegistrationServer.java is의 create 메소드는 아래와 같이 바뀐다:
public registration.RegistrationPK create(
String theuser,
String password,
String emailaddress,
String creditcard)
throws registration.CreateException{
double balance=0;
Connection con = null;
PreparedStatement ps = null;;
try {
con=getConnection();
RegistrationImpl reg= new RegistrationImpl();
reg.theuser = theuser;
reg.password = password;
reg.emailaddress = emailaddress;
reg.creditcard = creditcard;
reg.balance = balance;
ByteArrayOutputStream regStore =
new ByteArrayOutputStream();
ObjectOutputStream regObjectStream =
new ObjectOutputStream(regStore);
regObjectStream.writeObject(reg);
byte[] regBytes=regStore.toByteArray();
regObjectStream.close();
regStore.close();
ByteArrayInputStream regArrayStream =
new ByteArrayInputStream(regBytes);
ps=con.prepareStatement(
"insert into registration (
theuser, theclass) values (?, ?)");
ps.setString(1, theuser);
ps.setBinaryStream(2, regArrayStream,
regBytes.length);
if (ps.executeUpdate() != 1) {
throw new CreateException ();
}
RegistrationPK primaryKey =
new RegistrationPKImpl();
primaryKey.theuser(theuser);
return primaryKey;
} catch (IOException ioe) {
throw new CreateException ();
} catch (CreateException ce) {
throw ce;
} catch (SQLException sqe) {
System.out.println("sqe="+sqe);
throw new CreateException ();
} finally {
try {
ps.close();
con.close();
} catch (Exception ignore) {
}
}
}
데이터베이스로부터 바이트를 추출하고, ObjectInputStream으로부터 읽혀질 수 있는 그 바이트들로부터 ByteArrayInputStream 생성하고, 다시 인스턴스를 생성하기 위해 readObject를 호출함으로써 객체는 얻어지고 재생성된다.
다음 예는 데이터베이스에서 registration 인스턴스를 추출하는 egistrationServer.refresh 메소드가 필요한 것을 보여준다.
private Registration refresh(RegistrationPK pk)
throws FinderException {
if (pk == null) {
throw new FinderException ();
}
Connection con = null;
PreparedStatement ps = null;
try {
con=getConnection();
ps=con.prepareStatement("
select theclass from
registration where theuser = ?");
ps.setString(1, pk.theuser());
ps.executeQuery();
ResultSet rs = ps.getResultSet();
if(rs.next()){
byte[] regBytes = rs.getBytes(1);
ByteArrayInputStream regArrayStream =
new ByteArrayInputStream(regBytes);
ObjectInputStream regObjectStream =
new ObjectInputStream(
regArrayStream);
RegistrationImpl reg=
(RegistrationImpl)
regObjectStream.readObject();
return reg;
}
else {
throw new FinderException ();
}
} catch (Exception sqe) {
System.out.println("exception "+sqe);
throw new FinderException ();
}
finally {
try {
rs.close();
ps.close();
con.close();
}
catch (Exception ignore) {}
}
}
BLOBs and CLOBs: 만약 데이터의 사이즈가 가변이라면, 다른 데이터를 가진 테이블에 큰 필드를 저장하는 것은 반드시 최적의 장소는 아니다. 크고 가변인 크기의 객체를 다루는 한 방법은 Large Objects(LOBs)를 사용하는 것이다. LOB는 레코드에서 실제 데이터베이스 필드를 포인트하는 로케이터(Locator- 실제로는 포인터인)를 사용한다.
LOB는 2가지 타입 : Binary Large Object(BLOB)와 Character Large Object(CLOB)이다. 여러분이 BLOB 혹은 CLOB를 액세스 할 때, 데이터는 클라이언트에 복사되지 않는다. 결과(resultset)으로 실제 데이터를 추출하려면, BLOB blob=getBlob(1) 혹은 CLOB clob=getClob(1)를 호출하여 포인터를 얻어야 하고, blob.getBinaryStream() 혹은 clob.getBinaryStream()를 호출하여 데이터를 추출한다.
'오래된글 > Java' 카테고리의 다른 글
EJB CMP의 단점 (0) | 2018.04.07 |
---|---|
Scrolling Result Sets (0) | 2018.04.07 |
JDBC driver types (0) | 2018.04.07 |
What is the way of Direct Memory Access in Java? (0) | 2018.04.07 |
Easy java Persistence (0) | 2018.04.07 |