zoukankan      html  css  js  c++  java
  • mybatis

    一.基本认识

    • mybatis是一个ORM框架
    • ORM:对象关系映射
    • mybatis对jdbc的重复代码进行了封装,依然需要自己写sql(比jdbc开发快,比jpa性能好)

    二.hello,mybatis

    2.1 导包

    • mybatis核心包 mybatis/mybatis-3.2.1.jar
    • mybatis的依赖包 mybatis/lib/*.jar
    • jdbc驱动包 mysql-connector-java-5.1.26-bin.jar

    2.2 基本准备(表,domain)

    • 库(mybatis) -> 表(product)【导入-resources准备sql脚本product.sql】
    • Product对象
     public class Product {
        private Long id;
        //产品名称
        private String productName;
        //成本价
        private Double costPrice;
        //销售价格
        private Double salePrice;
        //供应商
        private String supplier;
        //品牌
        private String brand;
        //折扣
        private Double cutoff;
        //产品类型
        private Long dir_id;
        //省略getter,setter与toString...
    }
    

    2.3 创建配置文件

    配置文件的位置要注意

    • 注:配置文件的代码可以去找:网上,官方文档,官方中文文档
    • 官方中文文档 : doc/mybatis-3.2.1.pdf

    image

    jdbc.properties:数据库的参数

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///mybatis
    jdbc.username=root
    jdbc.password=123456
    

    mybatis-config.xml:mybatis的核心配置

    <?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:配置(xml的一个根)-->
    <configuration>
        <!--引入jdbc.propeties文件-->
        <properties resource="jdbc.properties" />
        <!--
            environments:环境(多个环境)
                default="development":多个环境中默认使用的是哪一个环境
        -->
        <environments default="development">
            <!--
                 environment:某一个环境 id:就是这个环境的名称
            -->
            <environment id="development">
                <!--
                    transactionManager:事务管理(ACID)
                        type="JDBC|MANAGED" jdbc:简单jdbc事务 MANAGED:啥都不做
                -->
                <transactionManager type="JDBC"/>
                <!-- 数据源(连接池) POOLED: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>
            <!--引入(找到)写SQL的XML-->
            <mapper resource="cn/itsource/dao/ProductMapper.xml"/>
        </mappers>
    </configuration>
    

    ProductMapper.xml:sql语句

    <?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:根(每个xml都得有,不用管它的含义)
            namespace:命名空间(随便取个名称)
    -->
    <mapper namespace="cn.itsource.dao.ProductMapper">
        <!--
            select:代表这是一个查询语句
                id:代表这个查询语句的唯一命名
                    以后你要找到这条SQL: namespace+id
                    例:cn.itsource.dao.ProductMapper.getOne
                parameterType:参数类型
                    long -> Long  _long -> long
                resultType:返回的每一条结果的类型
                    注:返回类型的全限定名
        -->
        <select id="getOne" parameterType="long" resultType="cn.itsource.domain.Product">
            select * from product where id = #{id}
        </select>
    
    </mapper>
    

    2.4 测试

    1. 读取核心配置文件
    2. 获取SqlSession对象 SqlSessionFactoryBuilder -> SqlSessionFactory -> SqlSession
    3. 执行查询
    /**
     * ①. 想办法搞到核心配置文件 mybatis-config.xml
     * ②. 获取到它的核心对象 SqlSession【相当于是咱们JPA中的EntityManager对象】
     *          EntityManagerFactory -> EntityManager
     *          SqlSessionFactoryBuilder -> SqlSessionFactory -> SqlSession
     *  ③.SqlSession就可以CRUD..
     */
    @Test
    public void testHello() throws Exception{
        //①. 想办法搞到核心配置文件 mybatis-config.xml
        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
        //②.获取到它的核心对象 SqlSession
        // 2.1获到到SqlSessionFactory对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(reader);
        // 2.2获取到它的核心对象 SqlSession
        SqlSession session = factory.openSession();
    
        //③.获取到一个对象
        /**
         * String statement : 获取SQL的字符串 namespace+id
         * Object parameter : 参数传递
         */
        Product product = session.selectOne("cn.itsource.dao.ProductMapper.getOne",1L);
        System.out.println(product);
    
        //关闭session
        session.close();
    }
    

    三.工具类与CRUD

    3.1 准备MyBatisUtil

    • SqlSessionFactoryBuilder:只用于创建factory,用完就可以扔掉
    • SqlSessionFactory:重级量对象,创建后不要随便销毁(一个项目一个这个对象即可)
    • SqlSession :用于完成咱们的CRUD
    /**
     * MyBatis的工具类,主要就是为我们创建SqlSession对象
     */
    public class MyBatisUtil {
        //定义一个SqlSessionFactory对象
        /**
         * 一个对象写这个位置,而且是静态的,它是有线程安全问题的
         */
        private static SqlSessionFactory factory = null;
    
        /**
         * SqlSessionFactoryBuilder:唯一的作用就是创建SqlSessionFactory
         *      一旦用完就可以把它把抛弃了
         * 1.类加载的时候就会执行
         * 2.只会执行一次
         */
        static {
            try {
                factory = new SqlSessionFactoryBuilder().build(
                        Resources.getResourceAsReader("mybatis-config.xml")
                );
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static SqlSession openSession(){
            return factory.openSession();
        }
    
    }
    

    3.1 完成CRUD

    3.1.1 productMapper.xml

    <!--
        select:代表这是一个查询语句
            id:代表这个查询语句的唯一命名
                以后你要找到这条SQL: namespace+id
                例:cn.itsource.dao.ProductMapper.getOne
            parameterType:参数类型
                long -> Long  _long -> long
            resultType:返回的每一条结果的类型
                注:返回类型的全限定名
    -->
    <select id="getOne" parameterType="long" resultType="product">
        select * from product where id = #{id}
    </select>
    
    <!--resultType:返回的每一条结果的类型-->
    <select id="getAll" resultType="product" >
        select * from product
    </select>
    
    <!--
        添加一条数据
            useGeneratedKeys:是否要主键
            keyColumn="id":在数据库中名称叫id
            keyProperty="id":在类中也叫id
            主键会放到你传过来的对象中
    -->
    <insert id="save" parameterType="product"
            useGeneratedKeys="true" keyColumn="id" keyProperty="id">
      insert into product
      (productName,dir_id,salePrice,supplier,brand,cutoff,costPrice) values
      (#{productName},#{dir_id},#{salePrice},#{supplier},#{brand},#{cutoff},#{costPrice})
    </insert>
    
    <!--修改功能-->
    <update id="update" parameterType="product">
        update product set
            productName=#{productName},
            dir_id=#{dir_id},
            salePrice=#{salePrice},
            supplier=#{supplier},
            brand=#{brand},
            cutoff=#{cutoff},
            costPrice=#{costPrice}
            where id=#{id}
    </update>
    
    <!-- 删除功能 -->
    <delete id="delete" parameterType="long">
        delete from product where id=#{id}
    </delete>
    

    3.1.1 productDao中完成功能

    • 增删改需要提交事务
    package cn.itsource.dao.impl;
    
    import cn.itsource.dao.IProductDao;
    import cn.itsource.domain.Product;
    import cn.itsource.util.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    
    import java.util.List;
    
    public class ProductDaoImpl implements IProductDao {
    
        private final String NAMESPACE = "cn.itsource.dao.ProductMapper.";
        @Override
        public void save(Product product) {
            SqlSession session = null;
            try {
                session = MyBatisUtil.openSession();
                session.insert(NAMESPACE+"save",product);
                //提交事务
                session.commit();
            } catch (Exception e) {
                //回滚事务
                session.rollback();
                e.printStackTrace();
            } finally {
                session.close();
            }
        }
    
        @Override
        public void update(Product product) {
            SqlSession session = null;
            try {
                session = MyBatisUtil.openSession();
                session.update(NAMESPACE+"update",product);
                //提交事务
                session.commit();
            } catch (Exception e) {
                //回滚事务
                session.rollback();
                e.printStackTrace();
            } finally {
                session.close();
            }
        }
    
        @Override
        public void delete(Long id) {
            SqlSession session = null;
            try {
                session = MyBatisUtil.openSession();
                session.delete(NAMESPACE+"delete",id);
                //提交事务
                session.commit();
            } catch (Exception e) {
                //回滚事务
                session.rollback();
                e.printStackTrace();
            } finally {
                session.close();
            }
        }
    
        @Override
        public Product getOne(Long id) {
            SqlSession session = null;
            try {
                session = MyBatisUtil.openSession();
                return session.selectOne(NAMESPACE+"getOne",id);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                session.close();
            }
            return null;
        }
    
        @Override
        public List<Product> getAll() {
            SqlSession session = null;
            try {
                session = MyBatisUtil.openSession();
                return session.selectList(NAMESPACE+"getAll");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                session.close();
            }
            return null;
        }
    }
    

    四.细节处理

    4.1 添加的对象返回id

    • useGeneratedKeys:是否要使用主键
    • keyColumn="id":在数据库中名称叫id
    • keyProperty="id":在类中主键的名称id
    • 主键会放到你传过来的对象中
    <!--
        添加一条数据
    -->
    <insert id="save" parameterType="product"
            useGeneratedKeys="true" keyColumn="id" keyProperty="id">
      insert into product
      (productName,dir_id,salePrice,supplier,brand,cutoff,costPrice) values
      (#{productName},#{dir_id},#{salePrice},#{supplier},#{brand},#{cutoff},#{costPrice})
    </insert>
    

    4.2 别名的配置

    • 内置别名(int,long,..)/自定义别名(自己的类)
    • 别名不区分大小写
    • 自定义别名的配置
      • 每个对象单独配置别名 <typeAlias type="cn.itsource.domain.Product" alias="Product" />
      • 扫描包(这个包的对象都会取别名) <package name="cn.itsource.domain" />
    <?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:配置(xml的一个根)-->
    <configuration>
        <!--引入jdbc.propeties文件-->
        <properties resource="jdbc.properties" />
        <!--
            typeAliases:配置别名
                注:别名不区别大小写
        -->
        <typeAliases>
            <!-- type:类型   alias:别名-->
            <!--<typeAlias type="cn.itsource.domain.Product" alias="Product" />-->
            <!--为这个包下面的所有类取别名(就是类名)-->
            <package name="cn.itsource.domain" />
            <package name="cn.itsource.query" />
        </typeAliases>
        <environments default="development">
           ...
        </environments>
        <mappers>
           ...
        </mappers>
    </configuration>
    
    

    4.3 日志的处理

    • mybatis中是使用日志来显示sql的
    • 在资源根目录创建一个log4j.properties
    # ERROR错误的日志 WARN:警告 INFO:普通信息  DEBUG:调试日志  TRACE:日志
    log4j.rootLogger=ERROR, stdout
    #log4j.rootLogger=NONE
    #把左边包名改成你自己的包名
    log4j.logger.cn.itsource=TRACE
    # 日志打印到控制台中
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    # 日志打印的一种格式(可以灵活地指定布局模式)
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    # 日志打印的格式是什么样子的  %d:日期 %p:优先级 %c:类的全名  %m:输出的结果 %n:换行
    log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
    

    4.4 #与$的区别(面试题)

    • $只能从对象中取属性(getter属性)
    • #支持预编译方案(性能更好,安全性更高)
    • 优先使用#,有些拼接字符串的地方不支持,再使用$

    五.批量操作与动态SQL

    5.1 批量添加

    • sql: insert into 表名 (列名,列名) values (?,?),(?,?),...
    • 实现使用foreach
    <!--
        批量添加
         insert into employee (name,age,sex) values
                 ("小小良",45,false),("大二良",45,true)
        foreach:循环
            collection:遍历的集合
            item:每次遍历拿到的对象
            separator:分隔符(每个值都使用,隔开)
    -->
    <insert id="batchSave" parameterType="list">
        insert into employee (name,age,sex) values
        <foreach collection="list" item="e" separator=",">
            (#{e.name},#{e.age},#{e.sex})
        </foreach>
    </insert>
    

    5.2 批量删除

    • sql: delete from 表名 where id in(?,?,..)
    • 实现使用foreach
    <!--
        批量删除:DELETE FROM employee WHERE id in (?,?,?,...)
        传 : List<Long> ids
         foreach:循环
            collection:遍历的集合
            item:每次遍历拿到的对象
            separator:分隔符(每个值都使用,隔开)
            open:以什么开头
            close:以什么结尾
            index:遍历的索引
    -->
    <delete id="batchDelete" parameterType="list">
      delete from employee where  id in
      <foreach collection="list" item="id" separator="," open="(" close=")">
          #{id}
      </foreach>
    </delete>
    

    5.3 动态修改

    • 解决咱们以前的数据丢失问题
    • 对象中没有值就不做修改
    <!--
            动态修改:只修改有值的数据
    -->
    <update id="dynamicUpdate" parameterType="employee">
        update employee
        <set>
            <if test="name!=null">
                name=#{name},
            </if>
            <if test="age!=null">
                age=#{age},
            </if>
            <if test="sex!=null">
                sex=#{sex},
            </if>
        </set>
        where id=#{id}
    </update>
    

    今日扩展

    连接池

    比较流行的连接池有三个

    • Spring建议使用的DBCP
    • Hibernate建议使用的C3P0
    • 阿里连接池 druid -> 现在外面用得还是比较多

    mysql的数据库引擎

    • InnoDB : 支持事务,支持外键
    • MyISAM : 不支持事务,不支持外键(速度快)
  • 相关阅读:
    2014 非常好用的开源 Android 测试工具
    Android 开发最佳实践
    Java_综合案例DAO设计模式(重要)
    Java_Set接口
    Java_List
    Java_类集框架简介
    Java_对象序列化
    Java_打印流
    Java_IO编程
    Java_文件操作
  • 原文地址:https://www.cnblogs.com/13438145925xiaozheng/p/11380932.html
Copyright © 2011-2022 走看看