您的位置:首页 > 移动开发

NO.2 Mybatis 实际项目的使用

2017-11-04 21:55 267 查看
NO.2 Mybatis 实际项目的使用

依旧采用MVC的编程模式,分三个层,Controller,Service,Dao,Dao层用接口定义,UserDaoImpl实现接口Dao。

那么我们来考虑一个问题,是注入一个SqlSession还是注入一个SqlSessionFactory?

如果注入session可能存在资源的抢占,session过程中可能关闭,如果同时进行另一操作,可能因资源已关闭而报错(线程问题)。因此,应该注入factory,每次打开session,再关闭资源。

然而,每个方法中都要打开关闭资源,我们可以让mybatis自动生成模板,进行代理。

对传统Dao层代码需求:

1>在Dao层实现类中,存在大量模板方法,能否将其提炼模板方法,减少工作量。

2>将statementId硬编码到了Dao层实现类。

硬编码:指将可变变量用一个固定值来代替的方法。然而,若不是采用配置的方法,若想修改,必须修改源代码再进行编译。大部分程序语言里,可以将一个固定数值定义为一个标记,然后用这个特殊标记来取代变量名称。

在做足了应用准备工作后,下面我们举出具体的例子进行说明。

首先我们定义一个Dao层接口

package com.xt.mybatis.hi.user.dao;

import com.xt.mybatis.hi.user.entity.UserInfo;

public interface UserDao {

public UserInfo queryUserInfoById(Integer userId);
public void insertUserInfo(UserInfo ui);
public void deleteUserInfoById(Integer userId);
public void updateUserInfo(UserInfo ui);
}


然后,写一个Dao层的实现类

package com.xt.mybatis.hi.user.dao;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.xt.mybatis.hi.user.entity.UserInfo;

public class UserDaoImpl implements UserDao{

private SqlSessionFactory sqlSessionFacory;

public UserInfo queryUserInfoById(Integer userId) {
SqlSession ss = sqlSessionFacory.openSession();
//sqlSession调用的方法,返回的是泛型,没有强转,即使参数传入错误,依旧能编译,只是不能执行
UserInfo ui = ss.selectOne("com.xt.mybatis.queryUserInfoById",1);
ss.close();
return ui;
}

public void insertUserInfo(UserInfo ui) {
SqlSession ss = sqlSessionFacory.openSession();
ss.update("com.xt.mybatis.insertUserInfo",ui);
ss.commit();
ss.close();
}

public void deleteUserInfoById(Integer userId) {
SqlSession ss = sqlSessionFacory.openSession();
ss.update("com.xt.mybatis.deleteUserInfoById",4);
ss.commit();
ss.close();
}

public void updateUserInfo(UserInfo ui) {
SqlSession ss = sqlSessionFacory.openSession();
ss.update("com.xt.mybatis.updateUserInfo",4);
ss.commit();
ss.close();
}

public SqlSessionFactory getSqlSessionFacory() {
return sqlSessionFacory;
}

public void setSqlSessionFacory(SqlSessionFactory sqlSessionFacory) {
this.sqlSessionFacory = sqlSessionFacory;
}
}


从以上的方法中,我们能够看到存在大量模板方法,而我们的工作也是正在一步步减少代码的繁杂,多余,重复,这正是我们经常提及的提高代码服用性(去重思想)。

为了满足需求一,我们采用代理类Mapper来开发Mybatis。

采用mapper代理的方式进行dao层的开发,需要有几个约定(约定大于配置)

1:XXXMapper.xml中(sql所在的配置文件)的namespace值需要与Dao接口中的全类名相同 (确定了哪一个XXXMapper.xml配置文件)。

2:XXXMapper.java接口中的方法名与XXXMapper.xml中的statementId相同(确定了使用哪个sql)。

3:XXXMapper.java接口中的方法输入参数需要与XXXMapper.xml中的ParameterType定义的类型相同。

4:XXXMapper.java接口中的方法返回值类型需要与XXXMapper.xml中的resultType定义的类型相同。

(约定大于配置,也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。本质是说,开发人员仅需规定应用中不符约定的部分。)

类似的,首先我们定义一个Mapper接口

package com.xt.mybatis.hi.user.mapper;

import java.util.List;
import java.util.Map;
import com.xt.mybatis.hi.user.entity.UserInfo;

public interface UserMapper {

public List<UserInfo> queryUserInfoById(Integer userId);
public List<UserInfo> queryUserInfo(Map<String,String> map);
public void insertUserInfo(UserInfo ui);
public void deleteUserInfoById(Integer userId);
public void updateUserInfo(UserInfo ui);

}


然后,写一个Mapper的实现类

package com.xt.mybatis.hi.user.mapper;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import or
ba3a
g.junit.Test;

public class UserMapperTest {

SqlSession ss = null;

@Before
public void myBatisInit(){
try {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis/mybatis-config.xml"));
ss = sqlSessionFactory.openSession();
} catch (IOException e) {
e.printStackTrace();
}
}

@Test
public void queryUserInfoById(){
UserMapper um = ss.getMapper(UserMapper.class);
System.out.println("UserInfo----------->" + um.queryUserInfoById(2));
ss.close();
}

@Test
public void queryUserInfo(){
UserMapper um = ss.getMapper(UserMapper.class);
Map<String,String> map = new HashMap<String,String>();
map.put("userName", "jj");
map.put("telNo", "12414");
System.out.println("userInfo==============>" + um.queryUserInfo(map));
ss.close();
}
}


类似于上一篇博客中的sql语句的xml文件,我们同样的写一个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="com.xt.mybatis.hi.user.mapper.UserMapper">

<!-- 如果查询语句中的字段名与输出属性不一样,不能实现映射也就查询不到数据,但每次都要规定。
为了提高代码复用性,可以在userMapper.xml中配置resultMap——数据字段名与输出属性的一个对应。
type:代表输出的javaBean类型
主键<id column="数据库中的字段名" property="属性名"/>
当有多个查询条件时,可以将其封装到map中,传入参数为一个map,map一般声明在最上方。
-->

<resultMap type="com.xt.mybatis.hi.user.entity.UserInfo" id="userInfoMap">
<id column="user_id" property="userId" />
<result column="user_name" property="userName"/>
<result column="tel_no" property="telNo"/>
</resultMap>

<select id="queryUserInfoById" parameterType="map" resultMap="userInfoMap">
select * from user_info where user_id = #{userId}
</select>

<select id="queryUserInfo" parameterType="string" resultMap="userInfoMap">
select * from user_info where user_name like '%${userName}%' and tel_no = #{telNo}
</select>

<insert id="insertUserInfo" parameterType="com.xt.mybatis.hi.user.entity.UserInfo">
insert into user_info values (#{userId},#{userName},password(#{passwd}),#{telNo},#{email})
</insert>

<update id="updateUserInfo" parameterType="com.xt.mybatis.hi.user.entity.UserInfo">
update user_info set user_name = #{userName},tel_no = #{telNo},email = #{email} where user_id = #{userId}
</update>

<delete id="deleteUserInfoById" parameterType="int">
delete from user_info where user_id = #{value}
</delete>
</mapper>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息