Mybatis(二):Mybatis使用
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>