图文教程,技术交流
工具类的使用
上篇文章我们熟悉运用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 loggingconfiguration
log4j.rootLogger=ERROR,stdout
#注意 namespace为我们自己需要日志处理的路径名
log4j.logger.com.jujidi.model.User=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.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框架有一个独立且系统的认识,所以采用这种系统的教学方式,而不是一开始就是整合。我们会在学习过程中逐渐拓展,最终达到实际开发所需要的本领。
推荐阅读
1. MyBatis框架教程「入门起步」
2. MyBatis框架教程「实践与工具类封装」
3. 浅谈JavaWeb项目代码如何分层
4. 你真的懂「类的加载机制」吗?
本文分享自微信公众号 - Java后端(web_resource)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。