날짜별 글 목록: 2008년 2월 14일

객체생성 방법

1. new keyword
– 일반적으로 많이 쓰이는 방법

MyObject
object = new MyObject();

2. Class.forName()
– reflection을 이용해서 생성자 호출해서 생성

MyObject object = (MyObject)
Class.forName(“net.sjava.socket.Acceptor”).newInstance();

3. clone()
– clone() 를 통해 기존 오브젝트의 복제본을 사용, shallow copy본이기 때문에 주의 필요

MyObject mObject = new MyObject();
MyObject object = mObject.clone();

4. object deserialization
ObjectInputStream
inStream = new ObjectInputStream(testInputStream);

String, StringBuffer, StringBuilder 선택 기준

헐.. 출처는 http://www.mimul.com/pebble/default/2007/11/26/1196088660000.html 입니다..

아주 기본적이지만 잊기 쉽기 때문에 선택 기준을 적어봅니다. 실력은 아주 기본적인 곳에서 시작되죠. ^^

1.
String 객체는 불변이기 때문에 변하지 않는 문자열은 String을 사용한다.
2.
StringBuilder는 비동기방식이기 때문에 Single Thread 환경하에서, 변화되는 문자열의
사용한다.
3. StringBuffer 동기방식으로 저장되기 때문에 멀티쓰레드로 접근하거나 문자열이 변경될
경우에 사용한다.

DBCP와 iBatis를 통한 Connection Pooling 사용기

내용의 출처는 http://www.mimul.com/pebble/default/2007/12/09/1197199680000.html 입니다.

프로젝트 개발을 하다보면 light한 환경을 요하는 경우가 있습니다. 이럴 경우 spring framework를 대신하여 dbcp +
ibatis를 가지고 개발을 진행하는 경우도 발생할 것입니다. 이럴 경우 유용하리라 생각되어 설치과정을 공유합니다.
일단 Tomcat
환경에서 설치 과정을 설명하겠습니다.

1. DBCP 설치
 – 실치 과정은 여기
가시면 설치과정을 설명해 놓았습니다.
 
2. iBatis 설치
 – 여기에 가서 다운로드
 –
${ProjectWebRoot}/WEB-INF/lib에 ibatis-2.3.0.677.jar 카피

3.
sqlmap.xml 정의

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
        PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
        "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
    <properties resource="com/mimul/dwr/app/resource/database.properties"/>
    <settings
            cacheModelsEnabled="true"
            enhancementEnabled="true"
            lazyLoadingEnabled="true"
            maxRequests="40"
            maxSessions="20"
            maxTransactions="5"
            useStatementNamespaces="false"
            />
    <transactionManager type="JDBC">
        <dataSource type="DBCP">
            <property name="driverClassName" value="${driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>

            <!-- OPTIONAL PROPERTIES BELOW -->
                <property name="initialSize" value="5"/>
                <property name="maxActive" value="30"/>
                <property name="maxIdle" value="20"/>
                <property name="maxWait" value="60000"/>
                <property name="poolPreparedStatements" value="true"/>
                <property name="validationQuery" value="select 0 from dual"/>
                <property name="testOnBorrow" value="true"/>
                <property name="maximumActiveConnections" value="10"/>
                <property name="maximumIdleConnections" value="5"/>
                <property name="maximumWait" value="60000"/>
                <property name="logAbandoned" value="false"/>
                <property name="removeAbandoned" value="false"/>
                <property name="removeAbandonedTimeout" value="50000"/>
        </dataSource>
    </transactionManager>
    <sqlMap resource="com/mimul/dwr/app/sql/Mimul.xml"/>
</sqlMapConfig>

4.
com/mimul/dwr/app/resource/database.properties 정의

driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@mimuluserdb:1521:mimuluser
username=mimuluser
password=mimuluser

5.
com/mimul/dwr/app/sql/Mimul.xml 정의

 – DDL2iBatis.exe를 활용하여 자동
생성하게 하는 것이 개발 속도가 올라갑니다.

<?xml version='1.0'?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
    "http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="Mimul">
    <cacheModel id="mimul-cache" type="MEMORY">
        <flushInterval hours="24"/>
        <flushOnExecute statement="insertMimul"/>
        <flushOnExecute statement="updateMimul"/>
        <flushOnExecute statement="deleteMimul"/>
        <property name="reference-type" value="WEAK" />
    </cacheModel>
    <resultMap class="com.mimul.dwr.model.Mimul" id="mimul-result" >
        <result property="lseq" column="lseq" />
        <result property="sseq" column="sseq" />
        <result property="assetid" column="assetid" />
        <result property="title" column="title" />
        <result property="imgurl" column="imgurl" />
        <result property="vodurl" column="vodurl" />
        <result property="use" column="use" />
        <result property="chgdate" column="chgdate" />
    </resultMap>
    <select id="getMimul" resultClass="com.mimul.dwr.model.Mimul"
parameterClass="Integer" >
        <![CDATA[
            SELECT lseq, sseq, assetid, title, imgurl, vodurl, use, chgdate
            FROM   mimul
            WHERE  lseq = #lseq#
        ]]>
    </select>
    <update id="updateMimul" parameterClass="com.mimul.dwr.model.Mimul" >
        <![CDATA[
            UPDATE mimul
            SET    sseq = #sseq#,  assetid = #assetid#,  title = #title#, 
imgurl = #imgurl#,  vodurl = #vodurl#,  use = #use#, 
chgdate = #chgdate#
            WHERE  lseq = #lseq#
        ]]>
    </update>
    <insert id="insertMimul" parameterClass="com.mimul.dwr.model.Mimul" >
        <selectKey resultClass="int"  keyProperty="lseq" >
            SELECT mimul_lseq_seq.nextval as lseq FROM dual
        </selectKey>
        INSERT INTO mimul (lseq, sseq, assetid, title, imgurl, vodurl,
use, chgdate)
        VALUES (#lseq#, #sseq#, #assetid#, #title#, #imgurl#, #vodurl#,
#use#, #chgdate#)
    </insert>
    <delete id="deleteMimul" parameterClass="com.mimul.dwr.model.Mimul" >
        <![CDATA[
            DELETE FROM mimul
            WHERE  lseq = #lseq#
        ]]>
    </delete>
</sqlMap>

6. 
DAO에서 사용하기 위한 SqlConfig 객체 정의(dbcp+ibatis연결 정보 정의)

import java.io.File;
import java.io.Reader;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.jaeminara.common.log.LogPool;

public class SqlConfig {
    private static SqlMapClient sqlMap = null;
    private static SqlConfig instance_ = null;
  
    private SqlConfig() throws Exception
    {
        Reader reader = null;
        StringBuffer rsc = null;
        try {
            if (sqlMap == null) {
                rsc = new StringBuffer(200);
                rsc.append("com").append(File.separator);
                rsc.append("jaeminara").append(File.separator);
                rsc.append("dwr").append(File.separator);
                rsc.append("app").append(File.separator);
                rsc.append("sql").append(File.separator).append("sqlmap.xml");
             reader = Resources.getResourceAsReader(rsc.toString());
             sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
             reader.close();
            }
        } catch (Exception e) {
            System.out.println(e);
            throw e;
        } finally {
            if (reader != null)
                reader.close();
            reader = null;
            rsc = null;
        }
    }
  
    public static SqlConfig instance()
    {
        try {
            if (instance_ == null) {
                synchronized (SqlConfig.class) {
                    if (instance_ == null)
                        instance_ = new SqlConfig();
                }
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        return instance_;
    }

    /**
    * Return SqlMapClient for SDP schema
     *
     * @return
     */
    public static SqlMapClient getSqlMapInstance()
    {
        return sqlMap;
    }
}

7. DAO 클래스 정의

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.mimul.common.log.LogPool;
import com.mimul.dwr.model.getMimulByLSEQ;

public class MimulDao
{
    private SqlMapClient smc =
SqlConfig.instance().getSqlMapInstance();
  
    public void MimulDao() {}
  
    public Mimul getMimulByLSEQ(int lseq) throws Exception
    {
        Mimul mimul = null;

        try {
            if (lseq == 0) {
                LogPool.instance("DAO").debug("getMimulByLSEQ() : Parameter is null!");
                return null;
            }
        mimul = (Mimul) smc.queryForObject("getMimul", lseq);
        } catch (Exception e) {
            LogPool.instance("DAO").error(e);
            throw e;
        }
        return mimul;
    }
    // 기타 필요한 함수 정의
}

크게
어려운 점은 없습니다. 그리고 transaction 무결성을 보장하기 위해서는 executor.startBatch();와
executor.executeBatch(); transaction 처리 로직을 넣으시면 됩니다.
나머진 자동으로 iBatis에서 트랜젝션
자원의 할당 및 해지의 라이프사이클을 관리해 줍니다.

Generic Method 및 익셉션 처리 팁

출처는 http://satukubik.com/2007/12/16/java-tips-generic-method/ 입니다.

Generic
is a pretty powerful addition to Java 5. But often people only use
generic in the class and forget that generic can also be useful in
method. This post will discuss a pretty neat use of generic to avoid
casting and reduce duplication.

First, let start with the problem. Say that you have a lot of methods that catch exception and wrapped it with other exception.

public void methodName1() throws AnotherException1 {
try {
...
} catch (SpecificException1 e) {
throw new AnotherException1(e);
}
}
 
public void methodName2() throws AnotherException2 {
try {
...
} catch (SpecificException2 e) {
throw new AnotherException2(e);
}
}

Then, customer comes with another requirement that all exceptions
should be logged before thrown. Here… the obvious solution is like this:

public void methodName1() throws AnotherException1 {
try {
...
} catch (SpecificException1 e) {
AnotherException1 ex = new AnotherException1(e);
log(ex);
throw ex;
}
}
 
public void methodName2() throws AnotherException2 {
try {
...
} catch (SpecificException2 e) {
AnotherException2 ex = new AnotherException2(e);
log(ex);
throw ex;
}
}

But that solution is not that elegant because we have to add two
lines in every try catch. We can come up with a new method to simplify
the change.

public Exception logAndReturnException(Exception e) {
log(e);
return e;
}
 
public void methodName1() throws AnotherException1 {
try {
...
} catch (SpecificException1 e) {
throw (AnotherException1) logAndReturnException(new AnotherException1(e));
}
}
 
public void methodName2() throws AnotherException2 {
try {
...
} catch (SpecificException2 e) {
throw (AnotherException2) logAndReturnException(new AnotherException2(e));
}
}

That’s remove duplication but not that pretty since we have to add
casting in every place. Here, generic can be used to simplify and make
our code prettier.

public <E extends Throwable> E logAndReturnException(E e) {
log(e);
return e;
}
 
public void methodName1() throws AnotherException1 {
try {
...
} catch (SpecificException1 e) {
throw logAndReturnException(new AnotherException1(e));
}
}
 
public void methodName2() throws AnotherException2 {
try {
...
} catch (SpecificException2 e) {
throw logAndReturnException(new AnotherException2(e));
}
}

Pretty neat, right? With the same technique we can simulate lambda calculus or function calling in Java. Try it!


콜렉션(Collection) 초기화 개선

이 글에서는 콜렉션의 초기화하는 기본 방법과 조금 더 개선한 방법에 대해서 살펴보자. 이 글에서 개선의 관점은 코드의 가독성을 기준으로 한다.

1. 기본 방법

1.1 배열 초기화는 아래와 같이 사용할 수 있다.

String[] s = new String [] {"1", "2"};

1.2 콜렉션은 아래와 같이 사용할 수 있다.

List s = new ArrayList();
s.add("1");
s.add("2");

2. 개선한 방법

2.1 첫번째

List s = new ArrayList() {{ add("1"); add("2"); }};

위 코드는 아래처럼 풀어 볼수가 있다.

List s = new ArrayList() {
   {
      add("1");
      add("2");
   }
};

그러나, 이 코드는 개선된 코드라고 보여지지 않는다.

2.2 두번째

List s = Arrays.asList(new String[]{"1", "2"});

이 코드는 첫번째 방법보다는 비교적 개선된 모습이다.

2.3 세번째

List s = Arrays.asList("1", "2");

이 코드가 List을 초기화하는 가독성 좋은 코드이다.