java
-
MyBatis (3) SQL Mapper와 Bean 간의 property 전달2012.11.09
-
MyBatis (2) CRUD 예제 만들기2012.11.09
-
MyBatis (1) MyBatis 설정하기2012.11.09
-
Eclipse에서 Properties 파일 작업하기2012.05.11
iBatis2 (1) 설정하기
예제실행환경
- Java SE 6
- iBatis 2.3.5
- JUnit 4
- Eclipse Java EE IDE (Juno)
MySQL Table 준비하기
CREATE TABLE `user` ( `id` int(5) NOT NULL AUTO_INCREMENT, `username` varchar(16) NOT NULL, `password` varchar(16) NOT NULL, `level` tinyint(2) NOT NULL DEFAULT '0', `reg_date` date NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
SQL Maps 환경설정
SqlMapConfig.xml
<?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> <properties resource="exercise/resource/development.properties"/> <typeAlias type="exercise.domain.User" alias="User"/> <transactionManager type="JDBC"> <dataSource type="SIMPLE"> <property name="JDBC.Driver" value="${driver}"/> <property name="JDBC.ConnectionURL" value="${url}"/> <property name="JDBC.Username" value="${user}"/> <property name="JDBC.Password" value="${pass}"/> </dataSource> </transactionManager> <sqlMap resource="exercise/ibatis2/persistence/SqlMap.xml"/> </sqlMapConfig>
SQL Map XML
SqlMap.xml
<?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> <parameterMap id="userParameterMap" class="User"> <parameter property="username" jdbcType="VARCHAR"/> <parameter property="password" jdbcType="VARCHAR"/> <parameter property="level" jdbcType="TINYINT"/> <parameter property="regDate" jdbcType="VARCHAR"/> </parameterMap> <insert id="add" parameterMap="userParameterMap"> INSERT INTO user ( id, username, password, level, reg_date ) VALUES ( NULL, ?, ?, ?, ? ) </insert> <delete id="deleteAll"> DELETE FROM user </delete> <select id="count" resultClass="int"> SELECT COUNT(*) FROM user </select> </sqlMap>
Unit Test
TestSqlMap.java
package exercise.ibatis2.test; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import java.io.Reader; import java.sql.SQLException; import java.util.Arrays; import java.util.List; import org.junit.Before; import org.junit.Test; import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; import exercise.domain.User; public class TestSqlMap { static String resource = "exercise/ibatis2/persistence/SqlMapConfig.xml"; static Reader reader; static SqlMapClient sqlMap; List<user> users; @BeforeClass public static void setUpBeforeClass() throws Exception { reader = Resources.getResourceAsReader(resource); sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); } @Before public void setUp() throws Exception { users = Arrays.asList( new User("user1", "1234", 1, "2012-11-09"), new User("user2", "1234", 1, "2012-11-09"), new User("user3", "1234", 1, "2012-11-09") ); } @Test public void testAdd() { try { sqlMap.delete("deleteAll"); sqlMap.insert("add", users.get(0)); assertThat(1, is(sqlMap.queryForObject("count"))); } catch (SQLException e) { e.printStackTrace(); } } }
MyBatis (3) SQL Mapper와 Bean 간의 property 전달
목차.
- MyBatis 기본 설정
- CRUD 예제 만들기
- SQL mapper 파라메터 전달
MyBatis는 SQL Mapping XML 구문을 Java 코드로 변환시 디폴트로 PreparedStatement 구문으로 바꾸고 전달되는 파라메터 들을 PreparedStatement 구문의 파라메터 '?'로 대응시킨다.
<select id="user" parameterType="int" resultType="User"> SELECT * FROM user WHERE id = #{id} </select>
'#{id}'는 int 타입의 파라메터이며 결과는 User 객체에 저장된다. 이 SQL Mapping XML 구문은 다음과 같은 내용의 Java 구문으로 변환된다.
String user = "SELECT * FROM user WHERE id = ?"; PreparedStatement ps = conn.preparedStatement(user); ps.setInt(1, id);
빈과 SQL 매퍼간의 파라메터 전달시 MyBatis는 Java 원시타입(Primitive type)의 경우 프로퍼티 getter/setter를 가지지 않고 파라메터 전체가 값을 대신한다.
만일 여러 개의 파라메터를 전달해야 할 경우는 2 가지 방법 중 선택하여 사용할 수 있다. Map을 사용하는 방법과 Mapper Interface Class에 @Param 어노테이션을 사용하는 방법이 있다.
Map을 사용
SQL Mapping XML
<insert id="user" parameterType="map" resultType="User"> INSERT INTO user (username, password) VALUES (#{username}, #{password}) </insert>
Mapper Interface Class
public int addParamMap(Map<string, string> map);
Running Java Code
... Map<string, string> param = new HashMap<string, string>(); param.put("username", "user1"); param.put("password", "1234"); mapper.addParamMap(param);
@Param 어노테이션을 사용
SQL Mapping XML
<intert id="user"> INSERT INTO user (username, password) VALUES (#{username}, #{password}) </insert>
Mapper Interface Class
public int addParamAnnotation( @Param("username") String username, @Param("password") String password);
Running Java Code
mapper.addParamAnnotation("user1", "1234");
MyBatis (2) CRUD 예제 만들기
목차.
- MyBatis 기본 설정
- CRUD 예제 만들기
- SQL mapper 파라메터 전달
SQL Mapper
UserMapper.xml
<mapper namespace="exercise.mybatis3.persistence.UserMapper"> <insert id="add" parameterType="User" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user (username, password, level, reg_date) VALUES (#{username}, #{password}, #{level}, #{regDate}) </insert> <select id="get" parameterType="int" resultType="User"> SELECT id, username, password, level, reg_date AS 'regDate' FROM user WHERE id = #{id} </select> <select id="getAll" resultType="User"> SELECT id, username, password, level, reg_date AS 'regDate' FROM user </select> <delete id="delete" parameterType="int"> DELETE FROM user WHERE id = #{id} </delete> <delete id="deleteAll"> DELETE FROM user </delete> <select id="count" resultType="int"> SELECT COUNT(*) FROM user </select> <select id="lastId" resultType="int"> SELECT id FROM user ORDER BY id DESC LIMIT 1 </select> </mapper>
Mapper Interface Class
UserMapper.java
public interface UserMapper { public void add(User user); public User get(int id); public List<user> getAll(); public void delete(int id); public void deleteAll(); public int count(); public int lastId(); }
Domain Object
User.java
public class User implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String username; private String password; private Integer level; private String regDate; public User() { // TODO Auto-generated constructor stub } public User(String username, String password, Integer level, String regDate) { this.username = username; this.password = password; this.level = level; this.regDate = regDate; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getLevel() { return level; } public void setLevel(Integer level) { this.level = level; } public String getRegDate() { return regDate; } public void setRegDate(String regDate) { this.regDate = regDate; } @Override public boolean equals(Object comp) { User target = (User)comp; if (this.id.equals(target.id) && this.username.equals(target.username) && this.password.equals(target.password) && this.level.equals(target.level) && this.regDate.equals(target.regDate)) return true; else return false; } }
Unit test
TestUserMapper.java
public class TestUserMapper { static SqlSessionFactory sf; List<user> users; @BeforeClass public static void setUpBeforeClass() throws Exception { String resource = "exercise/mybatis3/persistence/mybatis-config.xml"; Reader reader = Resources.getResourceAsReader(resource); sf = new SqlSessionFactoryBuilder().build(reader, "testing"); } @Before public void setUp() { users = Arrays.asList( new User("user1", "1234", 1, "2012-11-09"), new User("user2", "1234", 1, "2012-11-09"), new User("user3", "1234", 1, "2012-11-09") ); } @Test public void testAdd() { SqlSession session = sf.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); mapper.deleteAll(); mapper.add(users.get(0)); assertThat(1, is(mapper.count())); } finally { session.close(); } } @Test public void testGet() { SqlSession session = sf.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); mapper.deleteAll(); mapper.add(users.get(0)); User user = mapper.get(mapper.lastId()); assertTrue((users.get(0)).equals(user)); } finally { session.close(); } } @Test public void testGetAll() { SqlSession session = sf.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); mapper.deleteAll(); for (User user : users) { mapper.add(user); } assertThat(users.size(), is(mapper.count())); } finally { session.close(); } } @Test public void testDelete() { SqlSession session = sf.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); mapper.deleteAll(); for (User user : users) { mapper.add(user); } mapper.delete(mapper.lastId()); assertThat(users.size() - 1, is(mapper.count())); } finally { session.close(); } } } }
MyBatis (1) MyBatis 설정하기
목차.
- MyBatis 기본 설정
- CRUD 예제 만들기
- SQL mapper 파라메터 전달
MyBatis는 iBATIS의 새로운 버전으로 국내에서 가장 많이 사용되는 ORM Framework 중 하나이다. MyBatis는 문서화가 잘 되어 있다고 하지만 막상 실전에 적용시키기에는 이전 버전인 iBATIS에 비해 예제가 부족한 듯하여 자료 정리겸 레퍼런스를 만들어 볼까 한다. 1
우선 MyBatis를 설정하고 간단한 예제를 만들어 본 다음, Spring 3로 Bean을 등록하는 예제로 확장시켜 볼 예정이다.
본 예제는 다음과 같은 개발환경하에서 작성되었다.
- Eclipse Java EE IDE (Juno)
- PropertiesEditor (by Sou Miyazaki)
- Java SE 6
- MyBatis-3.1.1
- JUnit 4
1. MySQL Table
CREATE TABLE user ( id INT(5) NOT NULL PRIMARY KEY AUTO_INCREMENT, username VARCHAR(16) NOT NULL, password VARCHAR(16) NOT NULL, level INT(2) NOT NULL DEFAULT '0', reg_date DATE NOT NULL );
2. Configuration
development.properties
url=jdbc:mysql://localhost/development?characterEncoding=utf-8 driver=com.mysql.jdbc.Driver user=development pass=test123
mysql-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="exercise/mybatis3/persistence/development.properties"/> <settings> <setting name="defaultExecutorType" value="REUSE"/> <setting name="useGeneratedKeys" value="true"/> </settings> <typeAliases> <!-- Type Aliases List --> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="JNDI"> <property name="initial_context" value="java:comp/env" /> <property name="data_source" value="jdbc/insure"/> </dataSource> </environment> <environment id="testing"> <transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${user}" /> <property name="password" value="${pass}" /> </dataSource> </environment> </environments> <mappers> <!-- Mapper List --> </mappers> </configuration>
3. SQL Mapper (CRUD)
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="exercise.mybatis3.persistence.UserMapper"> <insert id="add" parameterType="User" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user (username, password, level, reg_date) VALUES (#{username}, #{password}, 1, NOW()) </insert> <select id="count" resultType="int"> SELECT COUNT(*) FROM user </select> </mapper>
UserMapper.java
package exercise.mybatis3.persistence; import exercise.mybatis3.domain.User; public interface UserMapper { public void add(User user); public int count(); }
4. Domain Object
User.java
package exercise.mybatis3.domain; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String username; private String password; private Integer level; private String regDate; public User() { // TODO Auto-generated constructor stub } public User(String username, String password) { this.username = username; this.password = password; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getLevel() { return level; } public void setLevel(Integer level) { this.level = level; } public String getRegDate() { return regDate; } public void setRegDate(String regDate) { this.regDate = regDate; } }
5. Unit Test (CRUD)
TestUserMapper.java
package exercise.mybatis3.test; import static org.junit.Assert.assertThat; import static org.hamcrest.CoreMatchers.is; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import exercise.mybatis3.domain.User; import exercise.mybatis3.persistence.UserMapper; public class TestUserMapper { static SqlSessionFactory sf; User user; @BeforeClass public static void setUpBeforeClass() throws Exception { String resource = "exercise/mybatis3/persistence/mybatis-config.xml"; Reader reader = Resources.getResourceAsReader(resource); sf = new SqlSessionFactoryBuilder().build(reader, "testing"); } @Before public void setUp() { user = new User("user1", "1234"); } @Test public void testAdd() { SqlSession session = sf.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); mapper.add(user); assertThat(1, is(mapper.count())); } finally { session.close(); } } }
- 데이터베이스와 객체와의 관계를 맵핑시켜 퍼시스턴스 로직처리를 도와주는 프레임워크 (Object Relational Mapping) [본문으로]
Eclipse에서 Properties 파일 작업하기
Properties 파일을 자바에서 사용할 수 있도록 하기 위해 UCS-2로 변환하여야 한다. 이때 한글과 같은 비 ASCII 코드의 경우 Lation1 인코딩으로 변환하여 저장하여야 하는데, 저장된 내용을 편집할 경우 여간 불편한게 아니다.
Properties Editor는 일본 프로그래머에 의해 만들어졌으며, Eclipse indigo의 경우 Help-Install New Software… 메뉴에 http://propedit.sourceforge.jp/eclipse/updates/ 경로를 추가하여 PropertiesEditor를 선택하여 설치하면 된다.