Mybatis原始的dao开发

首先给出直接通过传统的JDBC访问数据库实例

import java.sql.*;

/**
 * Created by hsc on 16/8/27.
 */
public class JdbcTest {
    private static final String DRIVER = "com.mysql.jdbc.Driver";
    private static String userName = "test"; //连接数据库用户名
    private static String password = "test123";//连接数据库的密码
    private static String connectionUrl = "jdbc:mysql://IP地址:端口/数据库名";


    public static void queryTest(String sql, Object[] params){

        //数据库的连接
        Connection connection = null;
        ResultSet resultSet = null;
        //预编译的Statement 向数据库发送sql语句,数据库那边进行编译,数据那边将编译结果存放在缓存
        PreparedStatement preparedStatement = null;

        try {

            Class.forName(JdbcTest.DRIVER);
            connection = DriverManager.getConnection(connectionUrl, userName, password);
            preparedStatement = connection.prepareStatement(sql);
            // 参数赋值,向占位符中填充数据
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    preparedStatement.setObject(i + 1, params[i]);
                }
            }

            resultSet = preparedStatement.executeQuery();

            //遍历查询结果集
            while (resultSet.next()) {
                System.out.println(resultSet.getString(1));
            }

        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            //释放资源
        } finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {

                    System.out.println(e.getMessage());
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String args[]) {
        //问号表示占位符
        String querySql = "select * from st_didinfo limit ?";
        Object[] objects = new Object[1];
        objects[0] = 5;
        queryTest(querySql, objects);

    }
}





从上面的程序不难发现有以下问题

1.使用时候创建,不使用的时候立即释放,对数据库进行频繁的连接和开启,造成了数据库资源的浪费,影响数据库的性能

2.将sql语句硬编码()到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统的维护

设想:如果能将sql语句配置在文件中,即使sql变化了,也不需要对java代码进行重新编译。

3.向PreparedStatement设置参数,对占位符把控设置和设置参数值,硬编码在java中利于系统的维护

4.从resultSet中遍历数据结果时候,存在硬编码,将表字段进行硬编码,不利于系统维护


Mybatis是持久层框架,是和数据库打交道的框架,

让程序员主要精力放在sql上,通过mybaits提供映射方式,自由灵活生成满足需要的sql语句。

mybaits 可以将PreparedStatement中输入参数自动进行输入映射,将查询结果集灵活的映射成java对象(输出对象)

mybatis开发dao两种方法

1.原始的dao开发(程序需要编写dao接口和dao实现类)

2.mybatis的mapper接口(相当于到接口)代理开发方法

原始的dao开发:

流程图


SqlMapConfig.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>

	<!-- 加载属性文件 -->
	<properties resource="db.properties">

		<!--properties中还可以配置一些属性名和属性值  正常测试和异常测试
		 -->
		<!-- <property name="jdbc.driver" value=""/>  在元素体内首先读取的,然后会读取resource 或者url加载的属性,他会覆盖-->

	</properties>
	<!-- 全局配置参数,需要时再设置 可能需要调整一些比如开启二级缓存,延迟加载  -->
	<!-- <settings>
	
	</settings> -->
	
	<!-- 别名定义 -->
	<typeAliases>
		
		<!-- 针对单个别名定义
		type:类型的路径
		alias:别名
		方便后面sql输入输出映射的使用
		 -->
		<!-- <typeAlias type="com.mybatis.pojo.UserInfo" alias="userInfo"/> -->
		<!-- 批量别名定义 
		指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)

		-->
		<package name="com.mybatis.pojo"/>
		
	</typeAliases>
	<!--TypeHandler 类型处理器 java类型到JDBC类型转换-->
	
	<!-- 和spring整合后 environments配置将废除-->
	<environments default="development">
		<environment id="development">
		<!-- 使用jdbc事务管理,事务控制由mybatis-->
			<transactionManager type="JDBC" />
		<!-- 数据库连接池,由mybatis管理-->
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driver}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<!-- 加载 映射文件 -->
	<mappers>

		<mapper resource="sqlmap/UserInfo.xml"/>

	</mappers>
	
</configuration>

UserInfo.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">

<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 
注意:使用mapper代理方法开发,namespace有特殊重要的作用
ORM java 对象和关系(数据库的)进行映射

-->
<mapper namespace="test">


    <!--id是一个标识,用于开发程序使用  将sql语句封装到mappedStatement对象中,所以将id称为statement的id-->
    <!--#{}表示一个占位符号-->
    <!--#{id}:其中的id表示接收输入 的参数,参数名称就是id,如果输入 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称-->

    <!--resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。-->
    <select id="findUserInfoById" parameterType="java.lang.Integer" resultType="com.mybatis.pojo.UserInfo">
		SELECT * FROM UserInfo WHERE id=#{value}
	</select>

    <!-- 根据用户名称模糊查询用户信息,可能返回多条
    resultType:指定就是单条记录所映射的java对象 类型
    ${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。
    使用${}拼接sql,引起 sql注入
    ${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value
     -->
    <select id="findUserByName" parameterType="java.lang.String" resultType="com.mybatis.pojo.UserInfo">
		SELECT * FROM UserInfo WHERE userName LIKE '%${value}%'
	</select>

    <!-- 添加用户
    parameterType:指定输入 参数类型是pojo(包括 用户信息)
    #{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值
    -->
    <insert id="insertUserInfo" parameterType="com.mybatis.pojo.UserInfo">
        <!--

        将插入数据的主键返回,返回到user对象中

        SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键
        keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
        order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序
        resultType:指定SELECT LAST_INSERT_ID()的结果类型

         -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>

        insert into UserInfo(userName,age) value(#{userName},#{age})
        <!--
        使用mysql的uuid()生成主键
        执行过程:
        首先通过uuid()得到主键,将主键设置到user对象的id属性中
        其次在insert执行时,从userInfo对象中取出id属性值
         -->
        <!--  <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
            SELECT uuid()
        </selectKey>
        insert into UserInfo(userName,age) value(#{userName},#{age}) -->


    </insert>

    <!-- 删除 用户
    根据id删除用户,需要输入 id值

     -->
    <delete id="deleteUserInfoById" parameterType="int">
		delete from UserInfo where id=#{id}
	</delete>

    <!-- 根据id更新用户
    分析:
    需要传入用户的id
    需要传入用户的更新信息
    parameterType指定userInfo对象,包括 id和更新信息,注意:id必须存在
    #{id}:从输入 user对象中获取id属性值
     -->
    <update id="updateUserInfo" parameterType="userInfo">
		update UserInfo set userName=#{userName},age=#{age}
		 where id=#{id}
	</update>
    

</mapper>



UserInfoDao 接口类
package com.mybatis.dao;

import com.mybatis.pojo.UserInfo;

import java.util.Map;

/**
 * Created by hsc on 16/9/4.
 */
public interface UserInfoDao {

    public UserInfo findUserInfoById(int id) throws Exception;
    public int inserUserInfo(UserInfo userInfo) throws Exception;
    public int deleteUserInfoById(int id);
    public int updateUserInfo(UserInfo userInfo);
}
UserInfoDao 接口实现类

package com.mybatis.dao.Impl;

import com.mybatis.dao.UserInfoDao;
import com.mybatis.pojo.UserInfo;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.Map;

/**
 * Created by hsc on 16/9/4.
 */
public class UserInfoDaoImpl implements UserInfoDao {

    private SqlSessionFactory sqlSessionFactory;


    public UserInfoDaoImpl(SqlSessionFactory sqlSessionFactory)
    {
        this.sqlSessionFactory=sqlSessionFactory;
    }
    public UserInfo findUserInfoById(int id) throws Exception {

        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserInfo userInfo=  sqlSession.selectOne("test.findUserInfoById",id);
        sqlSession.close();

        return userInfo;

    }

    public int inserUserInfo(UserInfo userInfo) throws Exception {

        SqlSession sqlSession=sqlSessionFactory.openSession();
        int size=  sqlSession.insert("test.insertUserInfo",userInfo);
        sqlSession.commit();//插入要做提交
        sqlSession.close();

        return  size;

    }

    public int deleteUserInfoById(int id) {

        SqlSession sqlSession=sqlSessionFactory.openSession();
        int size=  sqlSession.delete("test.deleteUserInfoById",id);
        sqlSession.commit();//删除要做提交
        sqlSession.close();

        return  size;
    }

    public int updateUserInfo(UserInfo userInfo) {

        SqlSession sqlSession=sqlSessionFactory.openSession();
        int size=  sqlSession.delete("test.updateUserInfo",userInfo);
        sqlSession.commit();//更新要做提交
        sqlSession.close();

        return size;

    }
}

单元测试类

package com.mybatis.Test;

import com.mybatis.dao.Impl.UserInfoDaoImpl;
import com.mybatis.dao.UserInfoDao;
import com.mybatis.pojo.UserInfo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;

/**
 * Created by hsc on 16/9/4.
 */
public class UserInfoDaoTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void  initSqlFactory() throws Exception
    {

        String res="SqlMapConfig.xml";
        InputStream in= Resources.getResourceAsStream(res);
        //创建会话工厂
         sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
    }
    @Test
    public void testFindUserInfoById() throws Exception
    {
        UserInfoDao userInfoDao=new UserInfoDaoImpl(sqlSessionFactory);

        UserInfo userInfo=userInfoDao.findUserInfoById(1);
        System.out.println(userInfo.getUserName());
    }

    @Test
    public void testDeleteUserInfoById() throws Exception
    {
        UserInfoDao userInfoDao=new UserInfoDaoImpl(sqlSessionFactory);
        int size=userInfoDao.deleteUserInfoById(1);
        System.out.println(size);

    }

    @Test
    public void testInsertUserInfo() throws Exception
    {
        UserInfoDao userInfoDao=new UserInfoDaoImpl(sqlSessionFactory);
        UserInfo userInfo=new UserInfo();
        userInfo.setAge(18);
        userInfo.setUserName("张大雷");

        int size=userInfoDao.inserUserInfo(userInfo);
        System.out.println(size);
        System.out.println(userInfo.getId());

    }

    @Test
    public void testUpateUserInfo() throws Exception
    {
        UserInfoDao userInfoDao=new UserInfoDaoImpl(sqlSessionFactory);
        UserInfo userInfo=new UserInfo();
        userInfo.setAge(14);
        userInfo.setUserName("陈大雷");
        userInfo.setId(6);
        int size=userInfoDao.updateUserInfo(userInfo);

        System.out.println(size);

    }


}


原始dao开发方法(程序员需要写dao接口和实现类,需要向dao的实现类注入SqlSessionFactory,它是单例,是线程安全的
SqlSession 是线程不安全的,最佳应用场合是方法体内
总结原始dao开发的问题1.dao 接口实现类中存在大量模板或者重复的代码 2.依然存在硬编码

参考资料:传智燕青的课堂笔记







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值