SQL mapping
Mabatis
This post is a general start guidance of Mybatis.
1. Introduction
What is MyBatis?
MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.
2. Getting Started
2.1 Installation
To use MyBatis you just need to include the mybatis-x.x.x.jar
file in the classpath.
If you are using Maven just add the following dependency to your pom.xml
:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
2.2 Building SqlSessionFactory from XML
Every MyBatis application centers around an instance of SqlSessionFactory
. A SqlSessionFactory
instance can be acquired by using the SqlSessionFactoryBuilder
. SqlSessionFactoryBuilder
can build a SqlSessionFactory
instance from an XML
configuration file, or from a custom prepared instance of the Configuration class.
Building a SqlSessionFactory
instance from an XML
file is very simple. It is recommended that you use a classpath resource for this configuration, but you could use any InputStream
instance, including one created from a literal file path or a file://
URL. MyBatis includes a utility class, called Resources, that contains a number of methods that make it simpler to load resources from the classpath and other locations.
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
The configuration XML
file contains settings for the core of the MyBatis system, including a DataSource for acquiring database Connection instances, as well as a TransactionManager
for determining how transactions should be scoped and controlled. The full details of the XML
configuration file can be found later in this document, but here is a simple example:
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- Every Mapper.XML needs to be stated here-->
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
While there is a lot more to the XML configuration file, the above example points out the most critical parts. Notice the XML
header, required to validate the XML document. The body of the environment element contains the environment configuration for transaction management and connection pooling. The mappers element contains a list of mappers – the XML files and/or annotated Java interface classes that contain the SQL code and mapping definitions.
## 2.3 mybatis Utils Class
Now that you have a SqlSessionFactory
, as the name suggests, you can acquire an instance of SqlSession
. The SqlSession
contains absolutely every method needed to execute SQL commands against the database. You can execute mapped SQL statements directly against the SqlSession
instance.
package com.danny.utils;
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 java.io.IOException;
import java.io.InputStream;
public class MybatisUtils {
//sqlSessionFactory --> sqlSession
private static SqlSessionFactory sqlSessionFactory;
static {
try{
// The first step: Obtain a sqlSession object
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch(IOException e){
e.printStackTrace();
}
}
//Since we have sqlSessionFactory,we can instantiate sqlSession Instances
// SqlSession contains all the functions that execute SQL commands
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
public static void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
MybatisUtils.sqlSessionFactory = sqlSessionFactory;
}
}
2.4 Writing Entity Class
- pojo directory:
package com.danny.pojo;
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getPwd() {
return pwd;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
Dao interface:
package com.danny.dao; import com.danny.pojo.User; import java.util.List; public interface UserDao { List<User> getUserList(); }
2.5 Exploring Mapped SQL Statements
At this point you may be wondering what exactly is being executed by the SqlSession
or Mapper
class. The topic of Mapped SQL Statements is a big one, and that topic will likely dominate the majority of this documentation. But to give you an idea of what exactly is being run, here are a couple of examples.
In either of the examples above, the statements could have been defined by either XML or Annotations. Let’s take a look at XML first. The full set of features provided by MyBatis can be realized by using the XML based mapping language that has made MyBatis popular over the years. If you’ve used MyBatis before, the concept will be familiar to you, but there have been numerous improvements to the XML mapping documents that will become clear later. Here is an example of an XML based mapped statement that would satisfy the above SqlSession
calls.
<?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">
<!--namespace=combine a corresponding Dao/Mapper interface-->
<mapper namespace="com.danny.dao.UserDao">
<!-- SQL statements -->
<select id="getUserList" resultType="com.danny.pojo.User">
select * from mybatis.user
</select>
</mapper>
2.5 Test
Notice that due to the fact that the convention of Maven is greater than its configuration, we may encounter the problem that our configuration file cannot be exported, the solution:
Add the following statements at the end of pom.XML
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
- The following is the testing code:
package com.danny.dao;
import com.danny.pojo.User;
import com.danny.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
//obtain sqlSession Object
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
//getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
sqlSession.close();
}
}
}
2.6 CRUD
- The package name in namespace has to be accordance with the interfaces in Dao/mapper.
- Select: SQL query statement.
id
: Corresponding function name in namesopace.resultType
: Returning value of SQL statement.parameterType
: Corresponding type of the passing parameter.
Write interfaces in
Dao/userMapper
:package com.danny.dao; import com.danny.pojo.User; import java.util.List; public interface UserMapper { // Query all the users List<User> getUserList(); // Query users according to ID User getUserId(int id); // Insert one user int addUser(User user); // Modify a user int updateUser(User user); }
Write the corresponding SQL statements in
Mapper.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"> <!--namespace=combine a corresponding Dao/Mapper interface--> <mapper namespace="com.danny.dao.UserMapper"> <!-- SQL statements --> <!--Selection--> <select id="getUserList" resultType="com.danny.pojo.User"> select * from mybatis.user </select> <select id="getuserId" parameterType="int" resultType="com.danny.pojo.User"> select * from mybatis.user where id = #{id} </select> <!--Insertion: the properties in the object can be pulled out--> <insert id="addUser" parameterType="com.danny.pojo.User"> insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd}); </insert> <update id="updateUser" parameterType="com.danny.pojo.User"> update mybatis.user set name=#{name},pwd=#{pwd} where id =#{id} ; </update> </mapper>
Test with Junit (Insertion, Deletion, Modification need to be committed ):
package com.danny.dao; import com.danny.pojo.User; import com.danny.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; public class UserDaoTest { // Test selection @Test public void test(){ //obtain sqlSession Object SqlSession sqlSession = MybatisUtils.getSqlSession(); try{ //getMapper UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.getUserList(); for (User user : userList) { System.out.println(user); } }catch (Exception e){ e.printStackTrace(); }finally { sqlSession.close(); } } // Test getter @Test public void getUser(){ SqlSession sqlsession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlsession.getMapper(UserMapper.class); User user =mapper.getUserId(1); System.out.println(user); sqlsession.close(); } // Test add user @Test public void addUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); int res = mapper.addUser(new User(3,"hhh","123456")); if (res > 0){ System.out.println("Insertion succeeded"); } // Commit changes sqlSession.commit(); sqlSession.close(); } // Test modify user @Test public void updateUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.updateUser(new User(1,"hehe","123123")); sqlSession.commit(); sqlSession.close(); } }