Java代码
/*
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。
使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次.
因此 SqlSessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
*/
private SqlSessionFactory sqlSessionFactory;
/*
从 XML 中构建 SqlSessionFactory
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的。
SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。
而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。
从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。
但是也可以使用任意的输入流(InputStream)实例,包括字符串形式的文件路径或者 file:// 的 URL 形式的文件路径来配置。
MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,可使从 classpath 或其他位置加载资源文件更加容易。
不使用 XML 构建 SqlSessionFactory
见官网
*/
@Before
public void before() throws IOException {
String resource = "mybatis/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// SqlSessionFactoryBuilder
// 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。
// 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void select() {
/*
依赖注入框架可以创建线程安全的、基于事务的 SqlSession 和映射器(mapper)并将它们直接注入到你的 bean 中,因此可以直接忽略它们的生命周期。
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。
也绝不能将 SqlSession 实例的引用放在任何类型的管理作用域中,比如 Servlet 架构中的 HttpSession。
每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。
应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭。
*/
/*
当Mybatis与一些依赖注入框架(如Spring或者Guice)同时使用时,SqlSessions将被依赖注入框架所创建,
所以你不需要使用SqlSessionFactoryBuilder或者SqlSessionFactory
*/
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
/*
映射器是创建用来绑定映射语句的接口。映射器接口的实例是从 SqlSession 中获得的。
因此从技术层面讲,映射器实例的最大作用域是和 SqlSession 相同的,因为它们都是从 SqlSession 里被请求的。
映射器实例的最佳作用域是方法作用域。也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可废弃。并不需要显式地关闭映射器实例
*/
UserDao dao = sqlSession.getMapper(UserDao.class);
User user = dao.findById(2L);
System.out.println(user);
} finally {
sqlSession.close();
}
}
@Test
public void add() {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setName("yangxuyue");
user.setUsername("yang");
user.setPassword("12345");
user.setPhone("12345678901");
user.setCreated(new Date());
user.setModified(new Date());
try {
UserDao dao = sqlSession.getMapper(UserDao.class);
dao.add(user);
// 当进行添加/更新/删除的时候,sqlSession需要进行提交事务
sqlSession.commit();
// 返回主键,Mapper.xml上实现,有两种方式
System.out.println(user.getId());
} finally {
sqlSession.close();
}
}
配置文件
mybatis-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>
<!--加载jdbc配置文件-->
<properties resource="jdbc/jdbc.properties"/>
<!--整合Spring后,environment不再被需要了-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 定义了 MyBatis 日志形式:输出到控制台 -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--加载*Mapper.xml-->
<mappers>
<mapper resource="mybatis/UserMapper.xml"/>
</mappers>
</configuration>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=utf-8&useSSL=false
jdbc.user=root
jdbc.password=
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="chapter14_mybatis.UserDao">
<!--
每一个sql语句都会被封装为MappedStatement对象,*Mapper.xml以Statement为单位管理sql语句
-->
<!--映射-->
<resultMap id="BaseResultMap" type="chapter14_mybatis.domain.User">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="phone" property="phone"/>
<result column="created" property="created"/>
<result column="modified" property="modified"/>
</resultMap>
<parameterMap id="User" type="chapter14_mybatis.domain.User"/>
<!--sql映射-->
<sql id="Base_Column_List">
id, name, username, password, phone, created, modified
</sql>
<!--查询-->
<select id="select" resultMap="BaseResultMap"
parameterType="java.util.Map">
SELECT
<include refid="Base_Column_List"/>
FROM user
<where>
<if test="id != null">
AND id=#{id}
</if>
<if test="name != null">
AND name=#{name}
</if>
<if test="username != null">
AND username=#{username}
</if>
<if test="password != null">
AND password=#{password}
</if>
<if test="phone != null">
AND phone=#{phone}
</if>
</where>
</select>
<!--查询角色-->
<select id="getRoles" resultType="chapter14_mybatis.domain.Role"
parameterType="java.util.Map">
SELECT r.*
FROM user_l_role l,user u,role r
WHERE l.user_id=u.id AND l.role_id=r.id
<if test="userId != null">
AND l.user_id=#{userId}
</if>
</select>
<!--新增用户-->
<!--返回主键-->
<!--方式一-->
<!--useGeneratedKeys="true" keyProperty="id">-->
<!--useGeneratedKeys="true" 表示给主键设置自增长-->
<!--keyProperty="id" 表示将自增长后的id赋值给实体类中的id字段。-->
<!--方式二-->
<!--<insert></insert> 中没有resultType属性,但是<selectKey></selectKey> 标签是有的。-->
<!--order="AFTER" 表示先执行插入语句,之后再执行查询语句。-->
<!--可被设置为 BEFORE 或 AFTER。-->
<!--SELECT LAST_INSERT_ID() 表示MySQL语法中查询出刚刚插入的记录自增长Id.-->
<!--实体类中uerId 要有getter() and setter(); 方法-->
<insert id="add" parameterMap="User">
<selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user(name, username, password, phone, created, modified)
VALUES (#{name},#{username},#{password},#{phone},#{created},#{modified})
</insert>
<!--根据id查询用户-->
<select id="findById" parameterType="java.lang.Long"
resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM user
WHERE id=#{id}
</select>
<!--更新用户-->
<update id="update" parameterMap="User">
UPDATE user
<set>
<if test="name != null">
name=#{name},
</if>
<if test="username != null">
username=#{username},
</if>
<if test="password != null">
password=#{password},
</if>
<if test="modified != null">
modified=#{modified},
</if>
<if test="phone != null">
phone=#{phone}
</if>
</set>
WHERE id=#{id}
</update>
<!--删除用户-->
<delete id="delete" parameterType="java.lang.Long">
DELETE FROM user
WHERE id=#{id}
</delete>
</mapper>