MyBatis学习记录-01

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yangqian201175/article/details/51282459

MyBatis是一个十分重要的持久层框架,在电商系统中应用广泛;今将Mybatis的学习经历记录如下;

  • MyBatis介绍
  • MyBatis框架原理
  • 基础入门
  • 映射文件的配置(包括动态SQL,输出映射以及输入映射)
  • MyBatis以及Hibernate技术选型要点与比较

  • 1、MyBatis介绍
    mybatis是一个对于JDBC进行封装的持久层框架。MyBatis框架的前身是ibatis。它在配置文件中编写sql,项目中真正的需求落实到实处就是数据库的操作,而mybatis就是专门用来直接编写sql来确保业务需求的完成。它可以对输入参数输出结果与java类型进行映射。它是不完整的orm映射框架。而正是因为以上的原因MyBatis的应用在业务需求灵活多变的公司以及项目上应用十分的广泛,比如在电商淘宝等项目上的应用。
  • MyBatis与JDBC的对比,JDBC中存在的问题
    首先看一份最简单的JDBC代码:
    // JDBC代码片段
    public static void main(String[] args) throws SQLException {
        //数据库连接
        Connection connection = null;
        //预编译statement
        //好处:防止 sql注入,提高数据的性能
        PreparedStatement preparedStatement = null;
        //结果集
        ResultSet resultSet = null;
        try {
            //加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //连接数据库
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis", "root", "1234");
            //定义sql语句,根据名称查询用户表的记录
            String sql = "SELECT * FROM USER WHERE username =  ?";
            //构造preparedStatement
            preparedStatement = connection.prepareStatement(sql);
            //向preparedStatement中占位符的位置设置参数
            preparedStatement.setString(1, "admin");
            //发起数据库查询请求,得到结果集
            resultSet = preparedStatement.executeQuery();
            //遍历查询结果
            while(resultSet.next()){
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                Date birthday = resultSet.getDate("birthday");
                System.out.println(id+"   "+username+"  "+birthday);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //释放资源
            if(resultSet!=null){
                resultSet.close();
            }
            if(preparedStatement!=null){
                preparedStatement.close();
            }
            if(connection!=null){
                connection.close();
            }
        }
    }
    • 总结:
    • 1、创建连接时存在硬编码;
    • 2、执行statement时存在硬编码;
    • 3、频繁的开闭数据库连接,会影响数据库的性能。

  • 2、MyBatis框架原理图:

    MyBatis运行流程图


  • 3、基础入门
    首先是一个比较简单的功能就是实现一个基本的增删改查的功能;
    使用工具:Myeclipse、Mysql数据库;
    首先创建JAVA工程项目,创建数据库Mybatis;

    • SQL片段:
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
insert  into `user`
(`id`,`username`,`birthday`,`sex`,`address`) 
values 
(1,'王五',NULL,'2',NULL),(10,'张三','2014-07-10','1','北京市'),
(16,'张小明',NULL,'1','四川省'),(22,'王小明',NULL,'1','四川省'),
(24,'张三丰',NULL,'1','四川省'),(25,'李小明',NULL,'1','四川省'),
(26,'王五',NULL,NULL,NULL);

MyBatis工程结构图

    • 由于MyBatis没有自带的日志文件系统,所以使用的是log4j的日志文件系统;
      log4j.properties日志文件配置如下:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# 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
    • 数据库相关信息配置db.properties:
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
db.username=root
db.password=1234
    • 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>
    <!-- 引用java的配置信息 -->
    <properties resource="db.properties" />
    <!-- 配置mybatis的环境信息,与spring整合之后,交由spring来管理数据信息 -->
    <environments default="development">
        <!-- id配置是为了方便数据库的改变的情况的配置,通过更改id就可以实现 -->
        <environment id="development">
            <!-- 配置JDBC事务控制,由mybatis进行管理 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源,采用mybatis连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="${db.driver}" />
                <property name="url" value="${db.url}" />
                <property name="username" value="${db.username}" />
                <property name="password" value="${db.password}" />
            </dataSource>
        </environment>
    </environments>
    <!-- 在sqlMapConfig.xml文件中加载user.xml文件 -->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
        <!-- 批量 -->
        <!-- <package name="com.mybatis.demo.mapper"/> -->
    </mappers>
</configuration>
    • 在config的source folder包下面的配置User.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的分类管理 -->
<!-- 重要:namespace在代理模式下开发具有十分重要的作用 -->
<mapper namespace="userDao">
    <!-- 根据用户Id查询用户 -->
    <!-- select:表示了一个查询的statement -->
    <!-- id:表示了该statement的唯一标示 -->
    <!-- #{}:表示一个占位符? -->
    <!-- parameterType表示的输入参数的Java类型 -->
    <select id="findUserByUserId" parameterType="int" 
        resultType="com.mybatis.demo.po.User">
        select * from user where id = #{value}
    </select>

    <!-- 利用用户名称进行模糊查询 -->
    <!-- ${}:表示一个sql的拼接符 -->
    <!-- ${value}:${}里面的id表示接受java类型的参数的参数名称,使用${}接受简单类型的时候,里面的值只能够是value -->
    <!-- 注意:${}会引起sql的注入,所以一定要慎用 -->
    <select id="findUserByName" parameterType="java.lang.String"
        resultType="com.mybatis.demo.po.User">
        select * from user where username like '%${value}%'    
    </select>

    <!-- 添加用户 -->
    <insert id="insertUser" parameterType="com.mybatis.demo.po.User">
        insert into user 
            (username,birthday,sex,address) 
            values
            (#{username},#{birthday},#{sex},#{address})
    </insert>

    <!-- 添加用户,使用select的方法首先查出主键 -->
    <!-- selectKey:可以通过sql查询主键,把主键信息封装到参数的POJO属性上 -->
    <!-- LAST_INSERT_ID:mysql的函数,通过它可以查询出主键的id,这个函数必须配合insert语句配合使用 -->
    <!-- order:selectKey里面sql的执行顺序,相当于insert语句 -->
    <insert id="insertUserId" parameterType="com.mybatis.demo.po.User">
        <selectKey keyProperty="id" resultType="int" order="BEFORE">
            SELECT LAST_INSERT_ID()
        </selectKey>
        insert into user 
            (username,birthday,sex,address) 
            values
            (#{username},#{birthday},#{sex},#{address})
    </insert> 

    <!-- 删除用户通过用户ID -->
    <delete id="deleteUser" parameterType="int">
        DELETE FROM USER WHERE id = #{id}
    </delete>

    <!-- 删除用户通过用户名称 -->
    <delete id="deleteUserName" parameterType="com.mybatis.demo.po.User">
        DELETE FROM USER WHERE username = #{username}
    </delete>

    <!-- 修改用户信息 -->
    <update id="updateUser" parameterType="com.mybatis.demo.po.User">
        UPDATE USER SET username = #{username},sex = #{sex} where id=#{id}
    </update>

</mapper>
  • 增删改查四种方法的初级使用
    增删改查四种方法

    • User_select.java
package com.mybatis.demo.client;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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 org.junit.Test;

import com.mybatis.demo.po.User;

public class User_select {
    //全局配置文件地址
    private final static String resource = "SqlMapConfig.xml";
    //创建SqlSessionFactory对象
    private static SqlSessionFactory sessionFactory = null;

    @Before
    public void config() throws IOException {
        //读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过配置文件创建SqlSessionFactory
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void test_select_id() throws Exception {
        //通过factory创建session
        SqlSession session = sessionFactory.openSession();
        //通过select查询User
        User user = session.selectOne("userDao.findUserByUserId",1);
        System.out.println(user);
        //关闭连接
        session.close();
    }
    @Test
    public void test_select_name() throws Exception {
        //通过factory创建session
        SqlSession session = sessionFactory.openSession();
        //通过select查询User
        List<User> users = session.selectList("userDao.findUserByName","王");
        System.out.println(users);
        //关闭连接
        session.close();
    } 

}
    • User_insert.java
package com.mybatis.demo.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

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 org.junit.Test;

import com.mybatis.demo.po.User;

public class User_insert {
    //全局配置文件地址
    private final static String resource = "SqlMapConfig.xml";
    //创建SqlSessionFactory对象
    private static SqlSessionFactory sessionFactory = null;

    @Before
    public void config() throws IOException {
        //读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过配置文件创建SqlSessionFactory
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test_insert_noId() throws Exception {
        //通过factory创建session
        SqlSession session = sessionFactory.openSession();
        User user = new User();
        user.setUsername("admin");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setAddress("江苏省南通市");
        session.insert("userDao.insertUser", user);
        //必须要执行事务
        session.commit();
        //关闭连接
        session.close();
    }

    @Test
    public void test_insert_hasId() throws Exception {
        //通过factory创建session
        SqlSession session = sessionFactory.openSession();
        User user = new User();
        user.setUsername("admin");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setAddress("江苏省南通市");
        session.insert("userDao.insertUserId", user);
        //必须要执行事务
        session.commit();
        //关闭连接
        session.close();
    }

}   
    • User_insert.java
package com.mybatis.demo.client;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

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 org.junit.Test;

import com.mybatis.demo.po.User;

public class User_delete {
    //全局配置文件地址
    private final static String resource = "SqlMapConfig.xml";
    //创建SqlSessionFactory对象
    private static SqlSessionFactory sessionFactory = null;

    @Before
    public void config() throws IOException {
        //读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过配置文件创建SqlSessionFactory
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test_delete() throws Exception {
        //通过factory创建session
        SqlSession session = sessionFactory.openSession();
        User user = new User();
        user.setUsername("admin");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setAddress("江苏省南通市");
        session.delete("userDao.deleteUserName", user);
        //必须要执行事务
        session.commit();
        //关闭连接
        session.close();
    }
}
    • User_update.java
package com.mybatis.demo.client;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

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 org.junit.Test;

import com.mybatis.demo.po.User;

public class User_update {
    //全局配置文件地址
    private final static String resource = "SqlMapConfig.xml";
    //创建SqlSessionFactory对象
    private static SqlSessionFactory sessionFactory = null;

    @Before
    public void config() throws IOException {
        //读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过配置文件创建SqlSessionFactory
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test_update() throws Exception {
        //通过factory创建session
        SqlSession session = sessionFactory.openSession();
        User user = new User();
        user.setId(1);
        user.setUsername("admin");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setAddress("江苏省南通市");
        session.update("userDao.updateUser", user);
        //必须要执行事务
        session.commit();
        //关闭连接
        session.close();
    }
}

  • 一些用法的区别:
  • 1)parameterType和resultType
    parameterType指定输入参数的java类型,可以填写别名或Java类的全限定名。
    resultType指定输出结果的java类型,可以填写别名或Java类的全限定名。
  • 2)#{}和${}
    • #{}:相当于预处理中的占位符?;
    • #{}:里面的参数表示接收java输入参数的名称;
    • #{}:可以接受HashMap、简单类型、POJO类型的参数;
    • 当接受简单类型的参数时,#{}里面可以是value,也可以是其他;
    • #{}可以防止SQL注入;
    • ${}:相当于拼接SQL串,对传入的值不做任何解释的原样输出;
    • ${}会引起SQL注入,所以要谨慎使用;
    • ${}可以接受HashMap、简单类型、POJO类型的参数;
    • 当接受简单类型的参数时,${}里面只能是value;
  • 3)主键生成策略
    MySQL可以使用自主主键获取以及调用数据库自身的UUID()函数进行获取
    Oracle主键返回策略
    Oracle没有自增主键,使用oracle的序列(可以生成流水号,类似 自增主键)生成主键。
    通过序列获取流水号方法:
    Select 序列名.next.val from dual

  • 4、映射文件的配置(包括动态SQL,输出映射以及输入映射)
    • 知识点一: 这一次使用代理的方式,有两种全局配置方法:

    两种方法


方法一的配置方法与sqlMap包下的User.xml的配置方法大同小异,但是UserMapper放置在src下的mapper包下的方法需要使用

<!-- 批量 -->
<package name="com.mybatis.demo.mapper"/>

UserMapper.java

package com.mybatis.demo.mapper;

import com.mybatis.demo.po.User;

public interface UserMapper {

    public User findUserByUserId(int id) throws Exception;

    public void insertUser(User user) throws Exception;

}

UserMapper.xml与User.xml内容相同
测试:(UserMapperTest)

package com.mybatis.demo.test;

import java.io.InputStream;

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 org.junit.Test;

import com.mybatis.demo.mapper.UserMapper;
import com.mybatis.demo.po.User;

public class UserMapperTest {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void setUp() throws Exception {
        //读取配置文件
        InputStream config = 
                Resources.getResourceAsStream("SqlMapConfig.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
    }

    @Test
    public void testFindUserById() throws Exception {
        SqlSession session = sqlSessionFactory.openSession();

        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = mapper.findUserByUserId(1);

        System.out.println(user);

        session.close();
    }
}

知识点二 :重点内容:
定义SQL语句片段,例子如下:

<!-- 定义sql语句片段 -->
<sql id="whereClause">
    <if test="user!=null">
        <if test="user.sex!=null and user.sex!=''">
            AND sex = #{user.sex}
        </if>
        <if test="user.username!=null and username!=''">
            AND username LIKE '%${user.username}'
        </if>
    </if>

    <!-- collection:表示接收到集合参数参数名称 -->
    <!-- item:遍历出来的项 -->
    <!-- open:遍历开始时要拼接的字符串 -->
    <!-- close:遍历结束时要拼接的字符串 -->
    <!-- separator:遍历过程中间要拼接的字符串 -->
    <if test="idList != null and idList.size > 0">
        <foreach collection="idList" item="id" open="AND id IN (" close=")"
            separator=",">
            #{id}
        </foreach>
    </if>
</sql>

  • 5、MyBatis与Hibernate的技术选型:(From MyBatis 课程)
  • Mybatis技术特点:
    1、通过直接编写SQL语句,可以直接对SQL进行性能的优化;
    2、学习门槛低,学习成本低;
    3、由于直接编写SQL语句,所以灵活多变,代码维护性更好。
    4、不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
    5、需要编写结果映射。
  • Hibernate技术特点:
    1、标准的orm框架,程序员不需要编写SQL语句。
    2、具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
    3、学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
    4、程序员不能自主的去进行SQL性能优化。

猜你喜欢

转载自blog.csdn.net/yangqian201175/article/details/51282459