zoukankan      html  css  js  c++  java
  • MyBatis(一)

    一、MyBatis简介

    MyBatis是一个对JDBC进行封装的持久层框架,只需关注SQL本身,而不必去处理(注册驱动、创建connection、创建statement、手动设置参数、结果集检查)的代码。

    XML或注解将要执行的statement配置起来,通过Java对象和statement的sql进行映射,生成最终的sql语句,由MyBatis框架执行sql并将结果映射成Java对象返回。

    MyBatis和Hibernate的区别:

    1、不完全的ORM框架,需要sql语句

    2、直接写sql语句,灵活度高,性能好

    3、与数据库相关(MySQL、Oracle用不同映射文件)

    JDBC存在的问题:

    1、创建连接connection、释放资源影响性能(数据库连接池可解决)

    2、(sql、参数、结果集)硬编码,代码不易维护

    二、MyBatis架构

    1、SqlMapConfig.xml是核心配置文件,配置运行环境等信息;Mapper.xml是映射配置文件,配置了操作数据库的sql语句,需要在SqlMapConfig.xml中配置。

    2、通过MyBatis环境等配置信息构造会话工厂SqlSessionFactory。

    3、由会话工厂SqlSessionFactory创建会话sqlSession,由sqlSession操作数据库。

    4、底层通过Executor执行器接口操作数据库,接口有两个实现:基本执行器、缓存执行器

    5、Mapped Statement也是一个底层封装对象,包装了MyBatis配置信息和sql映射信息等。映射配置文件Mapper.xml中一个sql对应一个Mapped Statement对象,sql的id即是MappedStatement的id。

    6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、POJO、Executor通过Mapped Statement在执行sql前将输入的Java对象映射至sql中,输入参数映射就是JDBC中对prepareStatement设置参数

    7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、POJO、Executor通过Mapped Statement在执行sql后将输出结果映射到Java对象中,输出结果映射过程相当于JDBC中对结果的解析处理过程。

    三、MyBatis入门

    1、导包

    核心包:MyBatis-3.2.7.jar

    依赖包:lib下所有包

    数据库驱动包:mysql-connector-java-5.1.17-bin.jar

    日志配置文件:log4j.properties

    2、在src下创建核心配置文件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>
        <!-- 和spring整合后 environments配置将废除-->
        <environments default="development">
            <environmentid="development">
            <!-- 使用jdbc事务管理-->
                <transactionManagertype="JDBC"/>
            <!-- 数据库连接池-->
                <dataSourcetype="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
                    <property name="username" value="root"/>
                    <property name="password "value="root"/>
                </dataSource>
            </environment>
        </environments>
    </configuration>

    3、创建POJO(JavaBean)  User,属性表与表中字段对应

    Public class User {
        privateintid;
        private String username;// 用户姓名
        private String sex;// 性别
        private Date birthday;// 生日
        private String address;// 地址
            
        setter&getter
    }

    4、在src下创建映射配置文件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">
    <mapper namespace="test">
    </mapper>

    namespace用于隔离sql语句

    5、加载映射文件User.xml到SqlMapConfig.xml

    <mappers>
            <mapperresource="sqlmap/User.xml"/>
    </mappers>

     

    四、增删改查用户

    1、根据ID查询用户信息

    1.1 User.xml中

    <!-- 根据id获取用户信息 -->
        <select id="findUserById" parameterType="Integer" resultType="cn.guojie.mybatis.domain.User">   // MyBatis已为Java.lang.Integer用别名Integer
            select * from user where id = #{id}
        </select>

    parameterType:入参类型,通过ONGL从输入对象中获取参数值拼接到sql中

    resultType:返回结果集类型,将sql查询结果的一行记录数据映射为resultType指定的类型对象

    #{id}:设置占位符,并将入参id传给sql

    1.2 测试

    public class UserTest {
        
        //会话工厂,单例,可重复使用
        private SqlSessionFactory sqlSessionFactory;
    
        @Before  // 在测试方法前执行
        public void createSqlSessionFactory() throws IOException {
            // 读取核心配置文件
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
    
            // 创建SqlSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder()
                    .build(inputStream);
    
        }
    
        // 根据 id查询用户信息
        @Test
        public void testFindUserById() {
            // 数据库会话实例
            SqlSession sqlSession = null;
            try {
                // 创建数据库会话实例sqlSession
                sqlSession = sqlSessionFactory.openSession();
                // 查询单个记录,根据用户id查询用户信息,查询多条记录用selectList,命名空间+.+sql中的id
                User user = sqlSession.selectOne("test.findUserById", 10);
                System.out.println(user);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }
    }

    2、根据用户名查询用户信息

    2.1 User.xml中

        <!-- 自定义条件查询用户列表 -->
        <select id="findUserByUsername" parameterType="java.lang.String"
                resultType="cn.guojie.mybatis.domain.User">
           select * from user where username like '%${value}%'  // 也可以是"%"#{id}"%"
        </selec

    ${}:拼接字符串,基本类型必须用value

    2.2 测试

    // 根据用户名称模糊查询用户信息
        @Test
        public void testFindUserByUsername() {
            // 数据库会话实例
            SqlSession sqlSession = null;
            try {
                // 创建数据库会话实例sqlSession
                sqlSession = sqlSessionFactory.openSession();
                // 模糊查询,查询用户名为张的用户
                List<User> list = sqlSession.selectList("test.findUserByUsername", "张");
                System.out.println(list.size());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }

    #{}和${}的区别:

    #{}:占位符,防止SQL注入,通常在=后

    ${}:拼串,只能是value,将参数拼接到sql中。在页面或者action中校验,不可输入SQL关键字和空格来防止SQL注入。通常在like后

    3、添加用户

    3.1  User.xml中

    <!-- 添加用户 -->
        <inser tid="insertUser" parameterType="cn.guojie.mybatis.domain.User">
          insert into user(username,birthday,sex,address) 
          values(#{username},#{birthday},#{sex},#{address})
        </insert>

    3.2 测试

    // 添加用户信息
        @Test
        public void testInsert() {
            // 数据库会话实例
            SqlSession sqlSession = null;
            try {
                // 创建数据库会话实例sqlSession
                sqlSession = sqlSessionFactory.openSession();
                // 添加用户信息
                User user = new User();
                user.setUsername("张小明");
                user.setAddress("河南郑州");
                user.setSex("1");
                user.setPrice(1999.9f);
                sqlSession.insert("test.insertUser", user);
                //提交事务,需要手动提交事务
                sqlSession.commit();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }

    4、MySQL自增主键返回

    用来查询上一个插入的ID

    <insert id="insertUser" parameterType="cn.guojie.mybatis.domain.User">
       <!-- selectKey将主键返回,需要再返回 -->
      <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
       </selectKey>
       insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address});
    </insert>

    LAST_INSERT_ID():数据库海曙,返回自增的主键

    keyProperty: 将返回的主键放入入参id中保存

    order:相对于insert语句的执行顺序

    resultType:id的类型,也就是keyproperties中属性的类型

    5、MySQL中用UUID实现主键

    <insert id="insertUser" parameterType="cn.guojie.mybatis.domain.User">
      <selectKey resultType="java.lang.String"  order="BEFORE" 
      keyProperty="id">
      select uuid()
      </selectKey>
      insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
    </insert>

    6、删除用户

    6.1 User.xml中

    <!-- 删除用户 -->
        <delete id="deleteUserById" parameterType="int">
            delete from user where id=#{id}
        </delete>

    6.2 测试

    // 根据id删除用户
        @Test
        public void testDelete() {
            // 数据库会话实例
            SqlSession sqlSession = null;
            try {
                // 创建数据库会话实例sqlSession
                sqlSession = sqlSessionFactory.openSession();
                // 删除用户
                sqlSession.delete("test.deleteUserById",18);
                // 提交事务
                sqlSession.commit();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }

    7、修改用户

    7.1 User.xml

    <!-- 更新用户 -->
    <update id="updateUser" parameterType="cn.guojie.mybatis.domain.User">
         update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
            where id=#{id}
    </update>

    7.2 测试

        @Test
        public void testUpdate() {
            // 数据库会话实例
            SqlSession sqlSession = null;
            try {
                // 创建数据库会话实例sqlSession
                sqlSession = sqlSessionFactory.openSession();
                // 添加用户信息
                User user = new User();
                user.setId(16);
                user.setUsername("张小明");
                user.setAddress("河南郑州");
                user.setSex("1");
                user.setPrice(1999.9f);
                sqlSession.update("test.updateUser", user);
                // 需要手动提交事务
                sqlSession.commit();
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (sqlSession != null) {
                    sqlSession.close();
                }
            }
        }

    SqlSession不是线程安全的,在方法体中创建与销毁

     

    五、DAO开发

    1、原始DAO开发(用得少)

    需要DAO接口及其实现类

    不足:

    (1) 方法中代码重复(sqlSessionFactory创建SqlSession,调用SqlSession的数据可操作方法)

    (2)硬编码(SqlSession操作方法需要指定statement的id)

    2、Mapper动态代理(常用) 

    只需Mapper接口(相当于DAO接口),MyBatis根据接口定义创建接口的动态代理对象

    2.1 开发规范

    (1)接口方法名和mapper.xml中id名相同

    (2)入参类型和mapper.xml中入参parammeterType相同

    (3)返回值类型和mapper.xml的返回类型resultType相同

    (4)接口类全路径(包名+类名)和mapper.xml中命名空间相同

    2.2  映射文件UserMapper.xml     放在mapper包下

    <?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="cn.guojie.mybatis.mapper.UserMapper">  ----> 4
    <!-- 根据id获取用户信息 -->
        <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">  ----> 1 2 3
            select * from user where id = #{id}
        </select>
    <!-- 自定义条件查询用户列表 -->
        <select id="findUserByUsername" parameterType="java.lang.String"
                resultType="cn.guojie.mybatis.domain.User">
           select * from user where username like '%${value}%' 
        </select>
    <!-- 添加用户 -->
        <inser tid="insertUser"parameter Type="cn.guojie.mybatis.domain.User">
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID() 
        </selectKey>
          insert into user(username,birthday,sex,address) 
          values(#{username},#{birthday},#{sex},#{address})
        </insert>
    
    </mapper>

    2.3 UserMapper接口  和映射文件放在同一目录

    Public interface UserMapper {
        //根据用户id查询用户信息
        public User findUserById(int id) throws Exception;
        //查询用户列表
        public List<User> findUserByUsername(String username) throws Exception;
        //添加用户信息
        publicvoid insertUser(User user)throws Exception; 
    }

    2.4 加载UserMapper.xml 

    <!-- 加载映射文件 -->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>

    2.5 测试

    Public class UserMapperTest {
    
        private SqlSessionFactory sqlSessionFactory;
        
        @Before
        protectedvoid setUp() throws Exception {
            // 加载mybatis配置文件
            String resource = "sqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 创建sessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }
    
        @Test
        Public void testFindUserById() throws Exception {
            // 获取session
            SqlSession session = sqlSessionFactory.openSession();
            // 获取mapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            // 调用代理对象方法
            User user = userMapper.findUserById(1);
            System.out.println(user);
            // 关闭session
            session.close();
            
        }
    
        @Test
        public void testFindUserByUsername() throws Exception {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            List<User> list = userMapper.findUserByUsername("张");
            System.out.println(list.size());
    
        }
    
      @Test
      Public void testInsertUser() throws Exception {
            //获取session
            SqlSession session = sqlSessionFactory.openSession();
            //获取mapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            //要添加的数据
            User user = new User();
            user.setUsername("张三");
            user.setBirthday(new Date());
            user.setSex("1");
            user.setAddress("北京市");
            //通过mapper接口添加用户
            userMapper.insertUser(user);
            //提交
            session.commit();
            //关闭session
            session.close();
        }
    }

     

    六、核心配置文件SqlMapConfig.xml

    1、<properties>

    在src下定义db.properties,其中不能有空格

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
    jdbc.username=root
    jdbc.password=root

    SqlMapConfig.xml中引用

    <properties resource="db.properties"/>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <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>
    </properties>

    2、<typeAliases> 别名

    <typeAliases>
        <!-- 单个别名定义 -->
        <typeAliasalias="user"type="cn.itcast.mybatis.po.User"/>
        <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->  // 常用
        <packagename="cn.guojie.mybatis.domain"/>
        <packagename="其它包"/>
    </typeAliases>

    3、<mapper>映射

    resource=UserMapper.xml的类路径

    class=UserMapper接口的类路径,要求mapper接口和mapper.xml同名且在同一目录中

    <package class="接口 " /> 注册包下所有接口(常用),要求mapper接口和mapper.xml同名且在同一目录中

    有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
  • 相关阅读:
    xml文件格式例如以下
    Nio学习3——基础模型:多路复用模型
    BP神经网络基本原理
    WPS2012交叉引用技巧,word比wps这点强更新參考文献
    hdu1023
    使用MERGE语句同步表
    商业软件编程非常无聊?
    jQuery Easy UI Panel(面板)组件
    很具体GC学习笔记
    cocos2dx-js学习笔记(一)环境搭建
  • 原文地址:https://www.cnblogs.com/1989guojie/p/7690022.html
Copyright © 2011-2022 走看看