工具类的使用
上篇文章我们熟悉运用MyBatis进行增删改查,并且手写了一个mybatis的工具类,学习了一些关於单元测试和关于日志的配置,没有看的读者请移步:MyBatis框架教程「实践与工具类封装」
这篇文章我们将通过一个案例继续学习MyBatis,并且达到熟练使用工具类的目的,注意:实践开发中的项目式不会使用工具类方式开发的,但是为了让读者学习的更全面理解这个框架,我就要更认真更系统的写教程。
小案例基本思路是:
我们在 MyBatisTest.java 中进行单元测试,单元测试中调用dao层实现类UserDaoImpl中的方法。在 UserDaoImpl.java 中运用我们手写的mybatis工具类进行获取sqlsession,执行映射文件中的sql,并把查询结果返回MyBatisTest.java中的调用方法以输出显示。
mybatis工具类用来完成加载核心配置文件,创建sqlsession工厂等工作,接下来继续我们案例的完成。
1. 项目截图
2. 导入Jar包
右键项目->Build Path 添加JUnit单元测试的支持
3. 添加Log4J的配置:
# Global loggingconfigurationlog4j.rootLogger=ERROR,stdout#注意 namespace为我们自己需要日志处理的路径名log4j.logger.com.jujidi.model.User=TRACE# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p[%t]-%m%n
4. 配置文件
<?xml version="1.0"encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTDConfig 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置环境 --> <environments default="jujidi"> <environment id="jujidi"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/dbname"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 加载映射文件 --> <mappers> <mapper resource="com/jujidi/model/UserMapper.xml"/> </mappers> </configuration>
这是Mybatis框架的核心配置文件,其中配置了相关环境和加载映射文件,环境中确定数据源,在数据源中配置你需要链接数据库的相关信息,比如用户名、密码。映射文件就是你编写SQL的xml,通过此核心配置文件进行加载关联。
5. MyBatisUtil.java
public finalclass MybatisUtil { private MybatisUtil(){} private static final String PATH = "mybatis-config.xml"; private static InputStream is = null; privates tatic SqlSessionFactory sqlSessionFactory = null; static{ try{ //加载核心配置文件 is = Resources.getResourceAsStream(PATH); //创建sqlsession工厂 -->相当于connection sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); }catch(IOException e){ e.printStackTrace(); throw new RuntimeException("加载映射文件失败可能是你的映射文件写错了原因:"+e.getMessage()); } } //获取sqlsession -->相当于执行sql语句对象 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } public static void closeSqlSession(SqlSession sqlSession){ if(sqlSession!=null){ sqlSession.close(); } } }
上方是一个MyBatis的工具类,根据核心配置文件创建sqlsession工厂,每一个SQL操作都要创建sqlsession工厂,我们就把创建工厂和获取sqlsession的共同代码提前出来,封装成工具类,便于以后调用。
6. UserDao.java
public interface UserDao { User load(Integer user_id); User login(Map<String , Object> map); User loginByUser(User user); }
7. UserDaoImpl.java
public class UserDaoImpl implements UserDao { SqlSession sqlSession = null; @Override public User load(Integer user_id ) { try{ sqlSession = MybatisUtil.getSqlSession(); //User.classgetName()是获取User model的全路径名 User user = sqlSession.selectOne(User.class.getName()+".load",user_id); return user; }catch(Exception e){ e.printStackTrace(); throw new RuntimeException("查询失败"+e.getMessage()); }finally{ MybatisUtil.closeSqlSession(sqlSession); } } @Override public User login(Map<String ,Object> map ) { try{ sqlSession = MybatisUtil.getSqlSession(); User user = sqlSession.selectOne(User.class.getName()+".login",map); return user; }catch(Exception e){ e.printStackTrace(); throw new RuntimeException("登录失败"+e.getMessage()); }finally{ MybatisUtil.closeSqlSession(sqlSession); } } @Override public User loginByUser(User user ) { try{ sqlSession = MybatisUtil.getSqlSession(); User u = sqlSession.selectOne(User.class.getName()+".loginByUser",user); return; }catch(Exception e){ e.printStackTrace(); throw new RuntimeException("登录失败"+e.getMessage()); }finally{ MybatisUtil.closeSqlSession(sqlSession); } } }
上面式UserDao接口的实现类,其中有三个方法:load、login、loginByUser,这些方法都是调用工具类来获取sqlSession,利用sqlSession来执行映射文件中的SQL,并且传递相关参数。可以通过全限定类名来找到对应的映射文件SQL。
8. User.java
public class User { private Integer userId; private String userName; private String account; private String pwd; private Integer status; }
注意:此处要生成getter,setter和tostring方法,为了更良好的浏览体验此处没有给出。
9. UserMapper.xml
<?xml version="1.0"encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTDMapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.jujidi.model.User"> <sql id="jujidi"> user_name userName,user_iduserId,account,password pwd,status </sql> <select id="load" parameterType="integer"resultType="com.jujidi.model.User"> select <include refid="jujidi"></include> from user where user_id=#{user_id} </select> <select id="login" parameterType="map"resultType="com.jujidi.model.User"> select <include refid="jujidi"></include> from user where account=#{account} and password=#{password} </select> <select id="loginByUser" parameterType="com.jujidi.model.User" resultType="com.jujidi.model.User"> select <include refid="jujidi"></include> from user where account=#{account} and password=#{pwd} </select> </mapper>
对于上方的配置文件我们给出两个注意:
注意一:上方的配置文件中的sql标签:
<sql id="jujidi"> user_name userName,user_iduserId,account,password pwd,status </sql>
上方SQL标签,可以在下方的Select语句中通过<include>标签来引入这条sql语句。
值得注意的是,我们上一篇文章讲过如果model 中的属性名和数据库中字段名称不相同是获取不到值的,但是我们现在可以通过上方sql标签的方法解决。
也就是说我们数据库中数据字段名称为:user_name,而我们的model中User的属性名字为:userName,我们可以通过类似下方语句:
Select user_name as userName from user
添加别名的方解决,当然 as 可以省略。
注意二:
<select id="login" parameterType="map"resultType="com.jujidi.model.User"> select <include refid="jujidi"></include> from user where account=#{account} and password=#{password} </select>
password=#{password} 中的#{password}必须是参数map的key,#{}会默认给包含的值加上单引号。
key 就是下方 MyBatisTest.java 文件中的map.put("password",value)的第一个参数。
并且 标签配置中password=#{password}中的 password(等号前的字段)要和数据库中的字段对应。
10. MyBatisTest.java:
public class MybatisTest { UserDao userDao = null; @Before public void init(){ userDao = new UserDaoImpl(); } @Test public void load() { User user = userDao.load(1); System.out.println(user); } @Test public void login() { Map<String , Object> map = new HashMap<String, Object>(); map.put("account" , "admin"); map.put("password" , "admin"); User user = userDao.login(map); System.out.println(user); } @Test public void loginByUser() { User user = new User(); user.setAccount("admin"); user.setPwd("admin"); User u = userDao.loginByUser(user); System.out.println(u); } }
上方是测试类,使用 @Before和 @Test 注解之前必须导入JUnit的相关Jar包,关于JUnit的介绍我们已经在前面文章讲过,可以翻翻MyBatis教程系列查看。在测试方法中分别测试3个方法,来完成对mybatis工具类的使用。
总结
这里我们已经可以熟练运用自己手写的MyBatis工具类了,而且我们掌握了单元测试基本的用法和简单的MyBatis的操作,对于工作中复杂的业务逻辑,仅仅简单的CRUD是无法胜任,我们在以后的文章将会讲解:模糊查询,动态sql语句等知识。
重要说明:实际开发中是不会使用Mybatis工具类来进行开发的,而是SSM框架整合后,通过接口代理的方式来实现对数据库的操纵。
为了使初学者对Mybatis框架有一个独立且系统的认识,所以采用这种系统的教学方式,而不是一开始就是整合。我们会在学习过程中逐渐拓展,最终达到实际开发所需要的本领。