클라이언트에서 ajax로 요청했을 때 자료를 손쉽게 파싱하기 위해서 json으로 클라이언트에 던져줄 때가 편할 때가 있습니다. 그래서 손쉽게 json으로 변환하는 라이브러리가 있습니다.

http://json-lib.sourceforge.net/

여기보면 json-lib라는 놈이 있는데 json으로 손쉽게 변환해주는 라이브러리입니다.

  • jakarta commons-lang 2.3
  • jakarta commons-beanutils 1.7.0
  • jakarta commons-collections 3.2
  • jakarta commons-logging 1.1
  • ezmorph 1.0.4

    이것들이 필요하다더군요. 위에 4개는 apache에 가면 있구요. ezmorph는 구글링해서 찾아서 받으세요.
    그리고 JSON-LIB인 json-lib-2.2.1-jdk15.jar가 필요합니다.

    사용법은 매우 간단합니다.
    [code]
    public class JsonTest {
     
     @Test
     public void Bean2Json()
     {
      MyBean myBean1 = new MyBean();
      myBean1.setId(1);
      myBean1.setName("mudchobo");
      MyBean myBean2 = new MyBean();
      myBean2.setId(2);
      myBean2.setName("shit");
     
      List<MyBean> mybeanList = new ArrayList<MyBean>();
      mybeanList.add(myBean1);
      mybeanList.add(myBean2);
     
      JSONArray jsonArray = JSONArray.fromObject(mybeanList);
      System.out.println("mybeanList - " + jsonArray);
     
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("beanlist", jsonArray);
     
      JSONObject jsonObject = JSONObject.fromObject(map);
      System.out.println("json - " + jsonObject);
     }
    }
    [/code]
    Bean 2개를 List에 add를 한다음에 JSONArray라는 객체가 List를 배열로 만드는놈입니다.

    mybeanList - [{"id":1,"name":"mudchobo"},{"id":2,"name":"shit"}]

    이런식으로 만듭니다.
    저거를 JSONObject클래스를 이용해서 앞에 이름을 붙여줍니다. Map을 이용하면 됩니다
    Map을 이용해서 put에서 첫번째 인자에 이름을 넣고, 두번째 인자에 방금 생성한 Array를 넣으면 됩니다.
    그리고 JSONObject.fromObject메소드를 이용해서 생성하게 되면 이렇게 됩니다.

    json - {"beanlist":[{"id":1,"name":"mudchobo"},{"id":2,"name":"shit"}]}

    이상입니다-_-;

  •  
    Posted by 머드초보
    ,
     

    이동국님이 번역해놓은 iBATIS SQL Maps 개발자 가이드를 보고있었습니다.
    INSERT를 한번에 많이 해야하는 상황이 발생해서 더 빠르게 하는 방법이 있나? 라는 생각이 들어서 가이드를 보고 있었습니다. 배치라는게 있었는데요.

    배치(Batches)
    만약 당신이 수행할 많은 수의 쿼리아닌 statement(insert/update/delete)를 가진다면 당신은 추가적인 최적화를 위해서 네트워크 트래픽을 줄이고 JDBC드라이버를 허락하는 배치 같은 작업을 수행하길 원할지도 모른다. 배치를 사용하는 것은 SQL Map API를 사용하면 간단하다. 배치의 경계를 지정하기 위해서 두가지 간단한 메소드를 제공한다.
    sqlMap.startBatch();
    //…execute statements in between
    sqlMap.executeBatch();
    executeBatch()를 호출함으로써 모든 배치 statement는 JDBC드라이버를 통해 수행될것이다.

    라는 글이 있더군요. 최적화를 시켜주는 것 같은데요. 그럼 더 빠른건가? 라는 생각에 삽질을 해봤습니다.

    [code]
    @Test
     public void testYesBatch()
     {
      StopWatch stopWatch = new StopWatch();

      stopWatch.start();
      try
      {
       sqlMapClient.startBatch();
       for(int i = 0 ; i < 100000 ; i++)
       {
        Testtemp testtemp = new Testtemp();
        testtemp.setId(i);
        testtemp.setName("성종천");
        sqlMapClient.insert("insertTesttemp", testtemp);
       }
       sqlMapClient.executeBatch();
      }
      catch(SQLException e)
      {
       e.printStackTrace();
      }
      stopWatch.stop();
      System.out.println("배치사용 걸린시간: " + stopWatch.getTotalTimeMillis());
     }
    [/code]
    Batch를 사용해서 시간을 측정해봤습니다. 100000건을 insert시켜봤는데, 198485가 나왔습니다.

    Batch를 안쓰고 해봤습니다.
    [code]
    @Test
     public void testNoBatch()
     {
      StopWatch stopWatch = new StopWatch();
      stopWatch.start();
      for(int i = 0 ; i < 100000 ; i++)
      {
       Testtemp testtemp = new Testtemp();
       testtemp.setId(i);
       testtemp.setName("성종천");
       sqlMapClientTemplete.insert("insertTesttemp", testtemp);
      }
      stopWatch.stop();
      System.out.println("배치미사용 걸린시간: " + stopWatch.getTotalTimeMillis());
     }
    [/code]
    100000건 insert하는데 202359나왔습니다.
    뭐지 이 차이없다는 것 같은 느낌은.....-_-;

    1000건 했을 때는 Batch사용시 20015, 미사용시 20032.......

    속도랑은 상관없이 최적화 하는건가-_-; 암튼 뭐 그렇습니다.

     
    Posted by 머드초보
    ,
     

    사용법은 초간단합니다.
    주로 성능 측정할 때 사용될 것이라고 생각되는데요.

    예전에 "자바 성능을 결정짓는 코딩습관과 튜닝이야기"라는 책에서도 StopWatch클래스가 나오는데요. 왠지 이놈이 저놈인 것 같네요.

    어쨌든 사용법은 간단합니다.

    [code]
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();

    // 처리할 내용~~~

    stopWatch.stop();
    System.out.println("걸린시간 : " + stopWatch.getTotalTimeMillis());
    [/code]
    이렇게 하면 저 사이에 처리하는데 걸리는 시간이 나옵니다.

     
    Posted by 머드초보
    ,
     

    일주일에 한번, 하루에 한번 작업을 수행하는 프로세스를 실행하고 싶을 때가 있을 껍니다.
    한가한 시간에 자동으로 배치작업을 실행하는 등의 작업을 자바에서 수행할 수 있습니다.
    Timer라는 클래스에다가 시작날짜, 시간을 설정한 뒤, TimerTask클래스를 상속받은 클래스에서 run메소드를 구현하게 되면 설정된 시간에 run메소드가 자동으로 수행되게 됩니다.

    코드를 보도록 합시다.

    [code]
    package com.mudchobo.scheduler;

    import java.util.TimerTask;

    public class WeeklySearch extends TimerTask {

     @Override
     public void run() {
      System.out.println("WeeklySearch!");
     }
    }
    [/code]
    TimerTask를 상속받아서 run메소드를 구현했습니다. run메소드는 간단히 WeeklySearch라고 보여주는군요.

    그럼 메인을 보도록 합시다.
    [code]
    package com.mudchobo.scheduler;

    import java.util.Calendar;
    import java.util.Timer;

    public class Scheduler {

     public static void main(String[] args) {
      WeeklySearch weeklySearch = new WeeklySearch();
     
      Timer timer = new Timer();
      Calendar date = Calendar.getInstance();
      date.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
      date.set(Calendar.AM_PM, Calendar.PM);
      date.set(Calendar.HOUR, 11);
      date.set(Calendar.MINUTE, 29);
      date.set(Calendar.SECOND, 0);
      date.set(Calendar.MILLISECOND, 0);
     
      timer.scheduleAtFixedRate(weeklySearch, date.getTime(),
        1000 * 60 * 60 * 24 * 7);
     }
    }
    [/code]
    Timer객체, Calendar객체를 선언합니다. Calendar객체에는 이 스케쥴이 시작될 시간을 설정해서 넣습니다. 그 뒤에 timer에 있는 scheduleAtFixedRate메소드에 첫번째 인자는 맨 위에서 생성한 TimerTask객체를 넣으면 되구요. 두번째는 이 스케쥴이 시작될 시간을 설정해서 넣으면 되구요. 3번째는 얼마만큼의 주기로 실행될 지 기간을 설정하게 됩니다.
    밀리초여서 1000밀리초 * 60초 * 60분 * 24시간 * 7일 하게 되면 저것은 1주일에 한번 실행되게 됩니다.

    이상입니다!

     
    Posted by 머드초보
    ,
     

    스프링에서 제공하는 트랜젝션을 MySQL과 Oracle에다가 적용을 해봤습니다.
    제가 잘 이해를 못하는 건지 모르겠는데, Oracle에서는 ReadOnly가 안먹혀요-_-;
    MySQL에서는 먹히는데....-_-; Oracle에서는 자체적으로 transaction에서 ReadOnly를 설정하는게 있더군요.
    또 Oracle은 트랜젝션기반이라고 하더라구요. 암튼, 참 어렵습니다-_-;
    우선 삽질한 코드입니다.
    MySQL로 해보았습니다.

    필요한 lib입니다.
    spring.jar - 스프링할껀데 필요하겠죠?-_-;
    commons-logging.jar - 스프링하려면 이눔이 있어야 돼요-_-; 위에 있는 lib와 종속돼요-_-;
    ibatis-2.3.0.677.jar - ibatis로 할껍니다. 이게 db연동을 쉽게 해주니까요-_-;
    mysql-connector-java-5.1.5-bin.jar - mysql connector가 필요하겠죠!

    프로젝트를 만듭시다. TestTransaction이라는 프로젝트를 만듭시다.
    최상위 src폴더에다가 applicationContext.xml파일을 만듭시다.

    applicationContext.xml
    [code]
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.springframework.org/schema/p"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

     <tx:annotation-driven />
     
     <!-- MySQL용 -->
     <bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:driverClassName="com.mysql.jdbc.Driver"
      p:url="jdbc:mysql://db주소"
      p:username="dbid" p:password="dbpw" />
     
       <!--  Transaction manager for iBATIS Daos -->
     <bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
      p:dataSource-ref="dataSource" />
     
     <!-- SqlMap setup for iBATIS Database Layer -->
     <bean id="sqlMapClient"
      class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"
      p:dataSource-ref="dataSource"
      p:configLocation="classpath:SqlMapConfig.xml" />
     
    <bean id="insertDataMysql" class="com.mudchobo.TestInsertMysql"
      p:sqlMapClient-ref="sqlMapClient"/>
    </beans>
    [/code]
    TestInsert라는 interface를 작성해봅시다.
    TestInsert.java
    [code]
    package com.mudchobo;

    import org.springframework.transaction.annotation.Transactional;

    public interface TestInsert {

     @Transactional(readOnly=true, rollbackFor={Throwable.class})
     public void insertData() throws Throwable;
    }
    [/code]
    인터페이스에다가 트랜젝션을 걸어도 되더라구요-_-; 구현되는 모든놈이 저 옵션으로 트랜젝션이 먹히는 듯 합니다. 근데 별로 안좋은 방법인듯한데-_-; 그냥 메소드에 거는게.....-_-; 보면 readOnly옵션에다가 Throwable예외가 발생하면 롤백합니다.

    구현해봅시다.
    TestInsertMysql.java
    [code]
    package com.mudchobo;

    import java.io.IOException;

    import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

    public class TestInsertMysql extends SqlMapClientDaoSupport implements
      TestInsert {

     @Override
     public void insertData() throws Throwable {
       getSqlMapClientTemplate().insert("insertData");
       System.out.println("mysql에 insert성공");
       throw new IOException();
     }
    }
    [/code]
    insert를 시키고, 강제로 IOException을 발생시켰습니다.

    ibatis xml부분을 봅시다.
    SqlMapConfig.xml
    [code]
    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE sqlMapConfig     
        PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"     
        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

    <sqlMapConfig>
     <sqlMap resource="Insert.xml" />
    </sqlMapConfig>
    [/code]
    Insert.xml
    [code]
    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE sqlMap     
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"     
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

    <sqlMap namespace="Sqlmap">
        <insert id="insertData">
         insert into TESTDATA (DATA) values ('MUDCHOBO')
        </insert>
    </sqlMap>
    [/code]
    보시면 단순 insert를 하고 있습니다-_-;

    main부분입니다.
    TestTransaction.java
    [code]
    package com.mudchobo;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class TestTransaction {
     public static void main(String[] args) throws Throwable{
      String[] configLocation = {"applicationContext.xml"};
      ApplicationContext context =
       new ClassPathXmlApplicationContext(configLocation);
     
      TestInsert testInsertMysql =
       (TestInsert) context.getBean("insertData");
      try {
       testInsertMysql.insertData();
      } catch (Throwable e) {
       System.out.println("예외발생");
      }
    }
    [/code]
    이걸 실행하면 트랜젝션이 readOnly이기 때문에 insert하려고 하면 에러가 나버리겠죠.
    Connection is read-only. Queries leading to data modification are not allowed; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
    요런 에러를 보실 수 있습니다.

    Oracle은 다음 장에서-_-;
    http://mudchobo.tomeii.com/tt/258 여기에 계속-_-;

     
    Posted by 머드초보
    ,