MyBatis是一个轻量级的ORM框架,它简化了对关系数据库的使用,开发人员可以在XML或注解中编写SQL来完成对数据库的操作,配置与使用简单,由于是手动写SQL,可控性好,便于SQL调优,而且如果完全使用XML方式,SQL语句可以集中维护,可以做到与Java代码完全隔离,也便于有DBA的团队对SQL调优。
MyBatis的大版本号是3.x,它的前身叫iBatis,创建于2002,最后一个版本是2.3.5 GA,2012年做了重大改进,改名为MyBatis,项目也从Apache迁移到了Google Code,目前最新版本是3.2.0,2003年2月21日发布。
GitHub站点:http://mybatis.github.com/mybatis-3/index.html
Google站点:https://code.google.com/p/mybatis/
iBatis退休声明:http://ibatis.apache.org/
下面通过一个例子快速体验一下MyBatis。
准备user表,用于示例
CREATE TABLE USER (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20),
create_time DATETIME,
PRIMARY KEY (id)
) ENGINE = innodb DEFAULT CHARSET = utf8;
初始化数据
INSERT INTO user (name, create_time) VALUES ('刘一', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('陈二', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('张三', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('李四', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('王五', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('赵六', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('孙七', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('周八', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('吴九', current_timestamp);
INSERT INTO user (name, create_time) VALUES ('郑十', current_timestamp);
第一步:pom.xml加入以下依赖。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.20</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.1.1</version>
</dependency>
第二步:编写domain类,注意包名。
public class User {
private Integer id;
private String name;
private Date createTime;
// getter, setter方法略
}
第三步:编写dao层,使用mybatis后,这一层可以只有接口,没有具体的类,注意包名。
package fun.elricboa.demo.mapper;
public interface UserMapper {
List<User> findAll();
}
第四步:编写dao层的mapper文件UserMapper.xml,放在fun.elricboa.demo.mapper包下。
<?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="fun.elricboa.demo.mapper.UserMapper">
<select id="findAll" resultType="User">
select * from user
</select>
</mapper>
注意:
1.mapper文件名(UserMapper.xml)要和上一步的接口名一致;
2.namespace属性必须为上一步接口的全类名:fun.elricboa.demo.mapper.UserMapper
第五步:编写mybatis配置文件 mybatis-config.xml ,放在src/main/resources下。
<configuration>
<properties resource="database.properties"/>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<package name="fun.elricboa.demo.domain"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="fun.elricboa.demo.mapper"/>
</mappers>
</configuration>
说明:
1.database.properties是数据库配置文件,也在src/main/resources下,引入这个文件后,后面就可引用数据库配置项。
2.typeAliases顾名思义,是类型的别名,这里配置为第二步domain类的包名,这样mybatis的mapper文件中就可以直接写类名,不必写类的全名。
3.mappers配置第三步dao层接口类的包名,告诉mybatis接口类及mapper文件的位置。
4.mapUnderscoreToCamelCase参数用于将下划线的命名格式转换为驼峰命名,如表字段名create_time,在domain类中定义为createTime,执行sql语句后,mybatis会自动把create_time转换为createTime,省去了写sql时指定别名的麻烦。
至此,代码编写完成,现在编写测试用例:
public class MyBatisTest {
@Test
public void test() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
// 通过selectList查询
List<User> userList = sqlSession.selectList(UserMapper.class.getName() + ".findAll");
for (User user : userList) {
logger.debug(user.toString());
}
logger.debug("------------------------------------------------------------------------");
// 通过接口类查询
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findAll();
for (User user : users) {
logger.debug(user.toString());
}
} finally {
sqlSession.close();
}
}
}
以上是最简单的查询,下面给出条件查询、增、删、改的示例
对UserMapper接口增加6个方法:
List<User> findAll();
User findById(Integer id);
List<User> findByIdList(List<Integer> userIdList);
int insert(User user);
int insertList(List<User> list);
int update(User user);
int deleteById(Integer id);
}
现在实现这6个方法,对于mybatis来说,就是在xml中写sql语句,修改UserMapper.xml:
<select id="findById" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
<select id="findByIdList" parameterType="list" resultType="User">
select * from user where id in
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<insert id="insert" keyProperty="id" parameterType="User">
insert into user(
name, create_time
) values (
#{name},
<choose>
<when test="createTime != null">
#{createTime}
</when>
<otherwise>
current_timestamp
</otherwise>
</choose>
)
</insert>
<insert id="insertList" parameterType="list">
insert into user(
name, create_time
) values
<foreach collection="list" item="item" open="(" close=")" separator="),(">
#{item.name},
<choose>
<when test="item.createTime != null">
#{item.createTime}
</when>
<otherwise>
current_timestamp
</otherwise>
</choose>
</foreach>
</insert>
<update id="update" parameterType="User">
update user
<set>
<if test = "name != null">name = #{name},</if>
<if test = "createTime != null">create_time = #{createTime},</if>
</set>
where
id = #{id}
</update>
<delete id="deleteById" parameterType="int">
delete from user where id = #{id}
</delete>
注意:mybatis对于事务的auto_commit是false,对于上面的insert、update、delete实现,在测试代码中需要手动提交事务,如:
@Test
public void testInsert() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setName("测试");
mapper.insert(user);
// 提交事务
sqlSession.commit();
} finally {
sqlSession.close();
}
}
如果需要自动提交事务,可以在调用openSession方法时传入参数,即sqlSessionFactory.openSession(true)