2011년 6월 13일 월요일

ThinkInSQL

Java로 개발된 Persistence Library로 현재 2008년 12월 13일 날짜로 최신 버전이 공개 되었다. 아래 Download Site에서 라이블러리와 Sample를 다운로드 받을 수 있다. 하지만 받아보면 알겠지만 아직은 아주 빈약하고 바로 설치해 쓸수도 없게 되어 있다.

Download Site
http://www.independentreach.com/thinkinsql.htm

Jar Package 만들기
Download 받은 ThinkInSql20081213.zip 파일의 확장자를 .jar 파일로 바꿔 사용하면 되는데 필자의 경우에는 zip 파일이 깨져 있어. ThinkInSqlSamples20081213.zip 파일을 받아 압축을 풀고 ir 디렉토리만 복사해 옮겨 "jar -cvf thinkinsql.jar ./ir" 명령어로 jar 파일을 생성하여 사용하였다.

ThinkInSQL의 특징
  1. Hibernate와 같은 Persistence 라이브러리와 다르게 POJO 클래스와 매핑되는 Table과 컬럼을 자동으로 생성해 주지 않는다. xml 파일에 DB Table 생성문을 작성해 넣어야 하고 작성시 클래스의 필드명과 테이블의 컬럼명은 반드시 동일해야 한다.
  2. "ir.thinkinsql.Database" 추상 클래스을 상속 받는 클래스을 만들어 DataBase을 연결하고 연결 방식에는 DataSource을 이용한 방법과 JDBC 드라이버를 이용하는 방법이 있다.
  3. SQL 문이 포함된 XML 파일은 일반적으로 DataBase연결 클래스와 동일한 Package 위치에 있게 되며 여러개의 XML 문서을 만들어 사용할 수 있다.
  4. "ir.thinkinsql.Database" 클래스의 beginTransaction() 메서드를 이용하면 autocommit flag를 off 할수 있다.
  5. "ir.thinkinsql.Database" 클래스의 generateClass() 메서드를 이용하면 기존 Table에서 POJO Class을 쉽게 생성할 수 있게 해준다.(.class가 생성되는게 아니라 .java을 만들수 있는 문자열을 리턴해준다.)
  6. 여러 DB 제품을 지원하게 하기 위해서는 각각 DB 제품에 맞는 SQL문이 포함된 XML을 만들어야 한다.
  7. Unique Key 조회을 제외한 다양한 조건으로 Persistence Object을 조회하기 위해서는 각 조건에 맞는 SQL을 작성해야한다.


Sample Code
sql.xml : Table Creat문장과 각종 조회 SQL 문을 포함
<?xml version="1.0" encoding="UTF-8"?>
<sql>
<OracleDb>
<createCustomer>
<![CDATA[
create table tCustomer (
customer_id integer,
customer_name varchar2(50),
inactive char(1),
type_code char(2),
PRIMARY KEY (customer_id)
)
]]>
</createCustomer>
<createSale>
<![CDATA[
create table tSale(
sale_id integer,
sale_desc varchar2(50),
customer_id integer,
sale_amount number(13,2),
customer_po varchar2(20),
PRIMARY KEY (sale_id,customer_id)
)
]]>
</createSale>
</OracleDb>
<SaleRec>
<isPoUsed>
<![CDATA[
select 1 from tSale where customer_po=? and sale_id<>?
]]>
</isPoUsed>
<selectByCustomerPO>
<![CDATA[
select * from tSale where customer_po=?
]]>
</selectByCustomerPO>
<selectForCustomer>
<![CDATA[
select * from tSale where customer_id=? order by sale_id
]]>
</selectForCustomer>
</SaleRec>
</sql>


droptable.xml : Table drop 문장이 포함(XML 파일 로딩 테스트을 위해서 sql.xml 파일에서 분리함.)
<?xml version="1.0" encoding="UTF-8"?>
<sql>
<Db>
<dropCustomer>
<![CDATA[
drop table tCustomer CASCADE CONSTRAINTS
]]>
</dropCustomer>
<dropSale>
<![CDATA[
drop table tSale CASCADE CONSTRAINTS
]]>
</dropSale>
</Db>
</sql>



OracleDb : DataBase연계 클래스로 DB연계 설정, XML 리소스등록 및 Persistence를 관리하는 메서드가 모두 포함된다.
package com.naver.blog.inter999.ir;
import ir.thinkinsql.Database;
public class OracleDb extends Database {

private static OracleDb db;

public static synchronized OracleDb getInstance() throws Exception {
if(db == null) {
db = new OracleDb();
// XML 리소스 추가
db.loadNamedStatements(db.getClass().getResource("droptable.xml"));
db.loadNamedStatements(db.getClass().getResource("sql.xml"));
db.open();
}
return db;
}
private OracleDb() {

}
//JDBC 방식을 이용한 Database 연동
public void open() throws Exception {
open(
"oracle.jdbc.driver.OracleDriver",
"jdbc:oracle:thin:@xxx.xxxx.xxx.xxx:1521:SID",
"사용자ID",
"비밀번호",
2, <- Connection Pool 수
"select * from tab");
try {
execute("Db.dropCustomer");
} catch (Exception e) {
System.out.println("Not Exist Table");
}
try {
execute("Db.dropSale");
} catch (Exception e) {
System.out.println("Not Exist Table");
}
execute("OracleDb.createCustomer");
execute("OracleDb.createSale");
}
}



CustomerRec : tCustomer Table과 매핑되는 POJO 클래스
package com.naver.blog.inter999.ir;
import ir.thinkinsql.BaseRecord;
import ir.thinkinsql.Database;
import java.util.List;

public class CustomerRec extends BaseRecord
{
public static final String TABLE = "tCustomer"; <- 매핑되는 Table 명을 반드시 기입
private long customer_id = 0;
private String customer_name="";
private boolean inactive=false;
private String type_code="XX";
public long getCustomerId()
{
return customer_id;
}
public String getCustomerName()
{
return customer_name;
}
public boolean getInactive()
{
return inactive;
}
public String getTable()
{
return TABLE;
}
public String getTypeCode()
{
return type_code;
}
public List<SaleRec> selectSales() throws Exception
{
return SaleRec.selectForCustomer(this.customer_id);
}
public void setCustomerId(long customer_id)
{
this.customer_id = customer_id;
}
public void setCustomerName(String customer_name)
{
this.customer_name = customer_name;
}
public void setInactive(boolean v)
{
this.inactive = v;
}
public void setTypeCode(String type_cd)
{
this.type_code = type_cd;
}
public Database getDatabase() throws Exception {
return OracleDb.getInstance();
}
}




SaleRec : tSaleTable과 매핑되는 POJO 클래스
package com.naver.blog.inter999.ir;
import ir.thinkinsql.BaseRecord;
import ir.thinkinsql.Database;
import java.math.BigDecimal;
import java.util.List;
public class SaleRec extends BaseRecord {
public static final String TABLE = "tSale";
private long customer_id = 0;
private String customer_po="";
private String sale_desc="";
private long sale_id = 0;
private BigDecimal sale_amount=new BigDecimal(0);
public BigDecimal getSaleAmount()
{
return sale_amount;
}
public void setSaleAmount(BigDecimal sale_amount)
{
this.sale_amount = sale_amount;
}
//sql.xml 파일에 등록된 selectByCustomerPO SQL문을 이용하고 조회된 row중 제일 첫번째 row만 리턴한다.
public static SaleRec selectByCustomerPO(String po) throws Exception
{
SaleRec r = new SaleRec();
if (r.getDatabase().selectFirst("SaleRec.selectByCustomerPO",r,po))
return r;
return null;
}
//sql.xml 파일에 등록된 selectForCustomer SQL문을 이용하고 조회된 모든 row을 리턴한다. "-1" 파라미터는 모든 리스트를 나타내며 "10"이면 10개만 가져오게 된다.
public static List<SaleRec> selectForCustomer(long cust) throws Exception
{
SaleRec r = new SaleRec();
return r.getDatabase().selectRows("SaleRec.selectForCustomer",r,-1,cust);
}
public long getCustomerId()
{
return customer_id;
}
public String getCustomerPo()
{
return customer_po;
}
public String getSaleDesc()
{
return sale_desc;
}
public long getSaleId()
{
return sale_id;
}
public String getTable()
{
return TABLE;
}
public boolean isPoUsed() throws Exception
{
return 0 < getDatabase().selectScalar("SaleRec.isPoUsed",0,customer_po,sale_id);
}
public void setCustomerId(long customer_id)
{
this.customer_id = customer_id;
}
public void setCustomerPo(String customer_po)
{
this.customer_po = customer_po;
}
public void setSaleDesc(String sale_desc)
{
this.sale_desc = sale_desc;
}
public void setSaleId(long sale_id)
{
this.sale_id = sale_id;
}
public Database getDatabase() throws Exception {
return OracleDb.getInstance();
}
}



Client Code
OracleSampleTestCase : JUnit 4로 작성한 TestCase
package com.naver.blog.inter999.ir.test;
import java.util.Date;
import java.util.List;
import org.junit.Test;
import com.naver.blog.inter999.ir.CustomerRec;
import com.naver.blog.inter999.ir.OracleDb;
import com.naver.blog.inter999.ir.SaleRec;
public class OracleSampleTestCase {

@Test
public void insertCustomerData() {
CustomerRec theCust = new CustomerRec();
try {
theCust.getDatabase().beginTransaction(); <- 사용자 transaction 시작

for (int i=1; i<=100; i++) {
theCust.setCustomerId(i);
theCust.setCustomerName("Customer " + i);
theCust.insert();
for (int j=1;j<=10;j++)
{
SaleRec theSale = new SaleRec();
theSale.setSaleId(j);
theSale.setCustomerId(theCust.getCustomerId());
theSale.setSaleDesc(new Date()+"");
theSale.setCustomerPo(theCust.getCustomerName() + ":" + j);
theSale.insert();
}
theCust = new CustomerRec();
}
theCust.getDatabase().commit();
} catch (Exception e) {
try {
theCust.getDatabase().rollback();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}

@Test
public void getCustomer() {
try {
CustomerRec cus15 = new CustomerRec();
if (cus15.select(15)) { <- key가 15인 Customer 정보를 가져온다.
System.out.println(cus15);
}
} catch (Exception e) {
e.printStackTrace();
}
}

@Test
public void getSale() {
try {
List<SaleRec> saleList = SaleRec.selectForCustomer(15);
for(SaleRec sale : saleList) {
System.out.println(sale);
}

} catch (Exception e) {
e.printStackTrace();
}
}

@Test
public void updateCustomer() {
CustomerRec cus15 = new CustomerRec();
try {
if (cus15.select(15)) {
cus15.setCustomerName("Hurukku !!!!");
}
cus15.getDatabase().beginTransaction();
cus15.update();
cus15.getDatabase().commit();
} catch (Exception e) {
try {
cus15.getDatabase().rollback();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}

@Test
public void generateClass() {
try {
OracleDb db = OracleDb.getInstance();
String clazz = db.generateClass("tcustomer", "NewCustomerRec");
System.out.println(clazz);
} catch (Exception e) {
try {
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}

댓글 없음:

댓글 쓰기

ETL 솔루션 환경

ETL 솔루션 환경 하둡은 대용량 데이터를 값싸고 빠르게 분석할 수 있는 길을 만들어줬다. 통계분석 엔진인 “R”역시 하둡 못지 않게 관심을 받고 있다. 빅데이터 역시 데이터라는 점을 볼때 분산처리와 분석 그 이전에 데이터 품질 등 데이...