2014年6月26日 星期四

[MyBatis]簡易CRUD教學

使用工具:
Eclipse Kepler Service Release 2
MySQL 5
使用API:
<mybatis.version>3.2.7</mybatis.version>
<mysql-connector-java.version>5.1.30</mysql-connector-java.version>
<slf4j-api.version>1.7.7</slf4j-api.version>
<slf4j-log4j12.version>1.7.7</slf4j-log4j12.version>
<log4j.version>1.2.17</log4j.version>

 

 流程:

1.建立測試用Table

2.配置 MyBatis 配置檔

3.建立 Table 對應之 java bean

4.建立 Table 對應之 Mapper

5.建立 Mapper對應之 Interface

6.建立 SqlSessionFactory

7.建立 Service

8.建立 TestUnit 

首先使用 MySQL 5 Workbench 建立 table


CREATE TABLE STUDENTS
(
stud_id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
email varchar(50) NOT NULL,
dob date DEFAULT NULL,
PRIMARY KEY (stud_id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

--塞入測試資料
insert into students(stud_id,name,email,dob) 
values (1,'Student1','student1@gmail.com','1983-08-09');
insert into students(stud_id,name,email,dob) 
values (2,'Student2','student2@gmail.com','1983-10-21');

--驗證
select * from students;

假設您使用 Maven 來建立專案, .pom 的 dependencies 配置 可以參考
我目前正在使用的配置檔

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.test</groupId>
  <artifactId>MyBatis_003</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>MyBatis_003</name>
  <url>http://maven.apache.org</url>

    <!-- 設定各dependency 使用的版本 -->
 <properties>
  <final_name>MyBatis_003</final_name>
  <jdk.version>1.6</jdk.version>
  <asm.version>3.3.1</asm.version>
  <asm-commons.version>3.3.1</asm-commons.version>
  <asm-tree.version>3.3.1</asm-tree.version>
  <commons-lang3.version>3.3.2</commons-lang3.version>
  <commons-fileupload.version>1.3.1</commons-fileupload.version>  
  <commons-logging.version>1.1.3</commons-logging.version>
  <commons-io.version>2.2</commons-io.version>
  <freemarker.version>2.3.9</freemarker.version>
  <junit.version>4.11</junit.version>
  <javassist.version>3.18.1-GA</javassist.version>
  <jquery.version>1.8.2</jquery.version>  
  <log4j.version>1.2.17</log4j.version>
  <mysql-connector-java.version>5.1.30</mysql-connector-java.version>
  <mybatis.version>3.2.7</mybatis.version>
  <ognl.version>3.0.8</ognl.version>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <struts2-core.version>2.3.16.3</struts2-core.version>
  <struts2-dojo-plugin.version>2.3.16.3</struts2-dojo-plugin.version>
  <struts2-json-plugin.version>2.3.16.3</struts2-json-plugin.version>
  <struts2-spring-plugin.version>2.3.8</struts2-spring-plugin.version>
  <struts2-junit-plugin.version>2.3.16.3</struts2-junit-plugin.version>
  <!-- 頁面排版用 siteMesh -->
  <struts2-sitemesh-plugin.version>2.3.16.3</struts2-sitemesh-plugin.version>
  <!-- Annotation 用 -->
  <struts2-convention-plugin.version>2.3.16.3</struts2-convention-plugin.version>
  <!-- 頁面排版用 siteMesh -->
  <sitemesh.version>2.4.2</sitemesh.version>
  <slf4j-api.version>1.7.7</slf4j-api.version>
  <slf4j-log4j12.version>1.7.7</slf4j-log4j12.version>
  <spring-test.version>3.2.0.RELEASE</spring-test.version>
  <spring-web.version>3.2.0.RELEASE</spring-web.version>
  <spring-context.version>3.2.0.RELEASE</spring-context.version>
  <spring-core.version>3.2.0.RELEASE</spring-core.version>
  <spring-beans.version>3.2.0.RELEASE</spring-beans.version>
  <xwork-core.version>2.3.16.3</xwork-core.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>${junit.version}</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts2-core</artifactId>
   <version>${struts2-core.version}</version>
  </dependency>
  <dependency>
   <groupId>commons-logging</groupId>
   <artifactId>commons-logging</artifactId>
   <version>${commons-logging.version}</version>
  </dependency>
  <dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-lang3</artifactId>
   <version>${commons-lang3.version}</version>
  </dependency>
  <dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>${commons-fileupload.version}</version>
  </dependency>
  <dependency>
   <groupId>freemarker</groupId>
   <artifactId>freemarker</artifactId>
   <version>${freemarker.version}</version>
  </dependency>
  <dependency>
   <groupId>org.javassist</groupId>
   <artifactId>javassist</artifactId>
   <version>${javassist.version}</version>
  </dependency>
  <dependency>
   <groupId>ognl</groupId>
   <artifactId>ognl</artifactId>
   <version>${ognl.version}</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts.xwork</groupId>
   <artifactId>xwork-core</artifactId>
   <version>${xwork-core.version}</version>
  </dependency>
  <dependency>
      <groupId>asm</groupId>
      <artifactId>asm</artifactId>
      <version>${asm.version}</version>
  </dependency>
  <dependency>
      <groupId>asm</groupId>
      <artifactId>asm-commons</artifactId>
      <version>${asm-commons.version}</version>
  </dependency>
  <dependency>
      <groupId>asm</groupId>
      <artifactId>asm-tree</artifactId>
      <version>${asm-tree.version}</version>  
  </dependency>   
  <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>${commons-io.version}</version>
  </dependency>
  <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>${log4j.version}</version>
  </dependency>
  <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql-connector-java.version}</version>
      <scope>runtime</scope>
  </dependency>
  <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-dojo-plugin</artifactId>
      <version>${struts2-dojo-plugin.version}</version>
  </dependency>
  <dependency>
   <groupId>com.efsavage.jquery</groupId>
   <artifactId>jquery-maven</artifactId>
   <version>${jquery.version}</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts2-json-plugin</artifactId>
   <version>${struts2-json-plugin.version}</version>
  </dependency>
  <!-- 
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-beans</artifactId>
   <version>${spring-beans.version}</version>
  </dependency>
  -->
  <!--
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${spring-core.version}</version>
  </dependency>
  -->
  <!--
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${spring-context.version}</version>
  </dependency>
  -->
  <!--
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${spring-web.version}</version>
  </dependency>
  -->
  <!--
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>${spring-test.version}</version>
  </dependency>
  -->
  <!--
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts2-spring-plugin</artifactId>
   <version>${struts2-spring-plugin.version}</version>
  </dependency>
  -->
  <!-- junit -->
  <!--
  <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-junit-plugin</artifactId>
      <version>${struts2-junit-plugin.version}</version>
  </dependency>
  -->
  <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-sitemesh-plugin</artifactId>
      <version>${struts2-sitemesh-plugin.version}</version>
  </dependency>
  <dependency>
      <groupId>opensymphony</groupId>
      <artifactId>sitemesh</artifactId>
      <version>${sitemesh.version}</version>
  </dependency>
  <dependency>
      <groupId>org.apache.struts</groupId>
      <artifactId>struts2-convention-plugin</artifactId>
      <version>${struts2-convention-plugin.version}</version>
  </dependency>
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>${mybatis.version}</version>
  </dependency>
  <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j-api.version}</version>
  </dependency>
  <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${slf4j-log4j12.version}</version>
  </dependency>            
 </dependencies>
 <build>
  <finalName>${final_name}</finalName>
  <plugins>
   <!-- 強制專案編輯使用的compiler版本 -->
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.0</version>
    <configuration>
     <source>${jdk.version}</source>
     <target>${jdk.version}</target>
     <encoding>${project.build.sourceEncoding}</encoding>
    </configuration>
   </plugin>

   <!-- 可產生java source -->
   <!-- 
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <executions>
     <execution>
      <id>attach-sources</id>
      <goals>
       <goal>jar</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
    -->

   <!-- 可產生javadoc 文件 -->
   <!-- 
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <executions>
     <execution>
      <id>attach-javadocs</id>
      <goals>
       <goal>jar</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
    -->

   <!-- 自動下載相關javadoc 及 source -->
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-eclipse-plugin</artifactId>
    <configuration>
     <downloadSources>false</downloadSources>
     <downloadJavadocs>true</downloadJavadocs>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>

本範例使用 xml 來設置對應的 mapper 無使用 Annotation
接下來先建立 MaBatis 所需要的 configuration file
在這邊我先設定為 mybatis-config.xml ,習慣上的放置位置在專案中的 resource 目錄中
mybatis-config.xml
properties 標籤 :放置外部配置
typeAliases 標籤:放置別名
environment 標籤:放置環境設定,以id為辨識名稱,可藉此切換環境設定
transactionManage 標籤:type分為JDBC / MANAGEN,JBDC適用於
Tomcat,MANAGEN 適用於 JBoss, WebLogic or GlassFish 這一類可使用EJB來管理
transaction 的環境
dataSource 標籤:type分為POOLED / UNPOOLED 兩種,POOLED 會建立一個連接池(
pool)來管理connection,而UNPOOLED 則是每次連結接建立一個新的 connection
typeHandlers 標籤:在Mappers xml檔案中的SQL對應的輸入資料屬性,如#{studID}等,
皆可自動對應java 的主要屬性及Wrapper,如String/Integer/enum等,若遇到非上述屬性內
的資料,比如說是一個自訂的Object,則需建立一個 extends BaseTypeHandler <T>
的類別,並複寫當中的Method,再藉由typeHandlers 去配置,讓MyBatis 可以找到對應
的資料類別。

<?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>
<!-- 設定jdbc相關配置檔 -->
<properties resource='jdbc.properties'/>
<!-- 設定對應名稱 -->
<typeAliases>
 <typeAlias alias="Student" type="com.Models.Student"/>
</typeAliases>
<environments default="development">
 <environment id="development">
  <transactionManager type="JDBC"/>
  <dataSource type="POOLED">
   <property name="driver" value="${jdbc.driverClassName}"/>
   <property name="url" value="${jdbc.url}"/>
   <property name="username" value="${jdbc.username}"/>
   <property name="password" value="${jdbc.password}"/>
  </dataSource>
 </environment>
</environments>
<mappers>
 <mapper resource="Models/StudentMapper.xml"/>
</mappers>
</configuration>

jdbc.properties 一樣放置在 resource 目錄中
 
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=admin

接著建立 Table Student 所對應的 java bean Student.java 

package com.Models;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Student {
 private Integer studId;
 private String name;
 private String email;
 private Date dob;
 
 @Override
 public String toString() {
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd",Locale.TAIWAN);
  System.out.println("studId=" + studId + " name=" + name + " email=" + email + " dob=" + sdf.format(dob));
  return super.toString();
 }
 
 public Integer getStudId() {
  return studId;
 }
 public void setStudId(Integer studId) {
  this.studId = studId;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 public Date getDob() {
  return dob;
 }
 public void setDob(Date dob) {
  this.dob = dob;
 }
}

接著建立 Student 對應的 Mapper 檔 StudentMapper.xml 
放置在 resource/Models 中

<?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="com.Models.mappers.StudentMapper">
 <resultMap type="Student" id="StudentResult">
  <id property="studId" column="stud_id"/>
  <result property="name" column="name"/>
  <result property="email" column="email"/>
  <result property="dob" column="dob"/>
 </resultMap>
 
 <select id="findAllStudents" resultMap="StudentResult">
  SELECT * FROM STUDENTS
 </select>
 
 <select id="findStudentById" parameterType="int" resultType="Student">
  SELECT STUD_ID AS STUDID, NAME, EMAIL, DOB 
  FROM STUDENTS WHERE STUD_ID=#{Id}
 </select>
 
 <insert id="insertStudent" parameterType="Student">
  INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) 
  VALUES(#{studId },#{name},#{email},#{dob})
 </insert>
</mapper>

接著建立 Interface for StudentMapper.xml StudentMapper.java
當中的三個 Method,正對應 StudentMapper.xml 中各標籤的 id
代表著該而 xml 的 SQL 語法正與該方法對應
parameterType 傳遞的參數型態
resultType 返回的參數型態  
resultMap 為一類別返回型態,而其中的 type="Student" Student 正是之前在
 mybatis-config.xml 中 typeAlias 標籤所設定的對應資料方便使用別名而不需使用
 com.Models.XXX 的全名
  
package com.Models.mappers;

import java.util.List;

import com.Models.Student;

public interface StudentMapper {
 List findAllStudents();
 Student findStudentById(Integer id);
 void insertStudent(Student student);
}

接下來建立一Util MyBatisSqlSessionFactory.java 用來建立 MyBatis 所需要的 SqlSessionFactory
 
package com.Utils;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisSqlSessionFactory {
 private static SqlSessionFactory sqlSessionFactory;
 
 public static SqlSessionFactory getSqlSessionFactory() {
  if(sqlSessionFactory==null) {
   InputStream inputStream;
   try {
    inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    } catch (IOException e) {
     throw new RuntimeException(e.getCause());
    }
  }
  return sqlSessionFactory;
 }
 public static SqlSession openSession() {
  return getSqlSessionFactory().openSession();
 }
}
接著建立一Service StudentService.java
準備用來存取資料用
package com.Services;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.Models.Student;
import com.Models.mappers.StudentMapper;
import com.Utils.MyBatisSqlSessionFactory;

public class StudentService {
 private Logger logger = LoggerFactory.getLogger(getClass());
 
 /**
  * 查詢全部學生
  * @return
  */
 public List findAllStudents()
 {
  SqlSession sqlSession = 
  MyBatisSqlSessionFactory.openSession();
  try {
   StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
   return studentMapper.findAllStudents();
  } finally {
  //If sqlSession is not closed 
  //then database Connection associated this sqlSession will not be returned to pool 
  //and application may run out of connections.
   sqlSession.close();
  }
 }
 
 /**
  * studId 尋找學生
  * @param studId
  * @return
  */
 public Student findStudentById(Integer studId)
 {
  logger.debug("Select Student By ID :{}", studId);
  SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
  try {
   StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
   return studentMapper.findStudentById(studId);
   //上面也可以用下面取代,不須再經過mapper手續
   //Student student = (Student)sqlSession. selectOne("com.mybatis3.mappers.StudentMapper.findStudentById", studId);
  } finally {
   sqlSession.close();
  }
 }
 
 /**
  * 新增學生
  * @param student
  */
 public void createStudent(Student student)
 {
  SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
  try {
   StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
   studentMapper.insertStudent(student);
   sqlSession.commit();
  } finally {
   sqlSession.close();
  }
 }
}

最後使用junit 來做測試 StudentServiceTest.java
 
package com.Tests;

import java.util.Date;
import java.util.List;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.Models.Student;
import com.Services.StudentService;

public class StudentServiceTest {
 private static StudentService studentService;
 
 @BeforeClass
 public static void setup(){
  studentService = new StudentService();
 }
 
 @AfterClass
 public static void teardown(){
  studentService = null;
 }
  
 @Test
 public void testFindAllStudents(){
  List students = studentService.findAllStudents();
  Assert.assertNotNull(students);
  for (Student student : students) {
   System.out.println(student);
  }
 }
 
 @Test
 public void testFindStudentById() {
  Student student = studentService.findStudentById(1);
  Assert.assertNotNull(student);
  System.out.println(student);
 }
 @Test
 public void testCreateStudent() {
  Student student = new Student();
  int id = 5;
  student.setStudId(id);
  student.setName("student_"+id);
  student.setEmail("student_"+id+"gmail.com");
  student.setDob(new Date());
  studentService.createStudent(student);
  Student newStudent = studentService.findStudentById(id);
  Assert.assertNotNull(newStudent);
 }
 }
參照資料:
Java Persistence with MyBatis 3

demo程式(右鍵另開視窗下載)

沒有留言 :

張貼留言