Hibernate:全自动
    黑箱操作,无法优化SQL 需要学HQL
mybatis:半自动框架 轻量级的框架
    自己写SQL 可以优化
    SQL与JAVA编码分离  配置文件配置即可
    <configuration>
        <environments default=\"a\">
            <environment id=\"a\">
                <transactionManager type=\"JDBC\"></transactionManager>
                <dataSource type=\"POOLED\">
                    <property name=\"driver\" value=\"com.mysql.jdbc.Driver\" />
                    <property name=\"url\" value=\"jdbc:mysql://localhost:3306/test\" />
                    <property name=\"username\" value=\"root\" />
                    <property name=\"password\" value=\"7777777\" />
                </dataSource>
            </environment>
        </environments>
        <!-- 将映射文件 注册到全局配置文件中 -->
        <mappers>
            <mapper resource=\"EmployeeMapper. \"/>
        </mappers>
    </configuration>

    -------------------
    <mapper namespace=\"com.mybatis.pojo.EmployeeMapper\">
        <!-- #{id}从传递过来的参数中取id值-->
        <select id=\"selectEmp\" resultType=\"com.mybatis.pojo.Employee\">
              SELECT id,last_name lastName,email,gender FROM employee WHERE id= #{id}
        </select>
    </mapper>
    -----------------------
            String resource = \"mybatis-config. \";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //获取sqlSession实例
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //第一个参数 唯一标识
            Employee employee = sqlSession.selectOne(\"com.mybatis.pojo.EmployeeMapper.selectEmp\", 1);
            System.out.println(employee);
            sqlSession.close();
            ---------------------------
新版本方法:
    namespace 指定为接口的全类名<mapper namespace=\"com.mybatis.mapper.EmployeeMapper\">
    将select的id改为方法的名称<select id=\"getEmpById\"

            String resource = \"mybatis-config. \";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //获取sqlSession实例
            SqlSession sqlSession = sqlSessionFactory.openSession();
    //        //第一个参数 唯一标识
    //        Employee employee = sqlSession.selectOne(\"com.mybatis.pojo.EmployeeMapper.selectEmp\", 1);
            EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
            Employee employee = mapper.getEmpById(1);
            System.out.println(employee);
            sqlSession.close();
原理:mybatis会为接口代理  增强并实现这个接口 对应的操作数据库的方法
------------------------------
注意:mybatis是非线程安全的  定义私有变量属性 private SqlSession sqlSession
        每次使用都要获取新的对象
   ------------------
   开启驼峰命名:
            <settings>
                <setting name=\"mapUnderscoreToCamelCase\" value=\"true\"/>
            </settings>
    如果属性名和数据库字段名就是不同:
        自定义映射:<Mapper><resultMap type=\"对象类型\" id=\"\"><result property=\"属性名\" column=\"字段名\">
        使用 将resultType 替换为 resultMap
        <resultMap id=\"resultmap\" type=\"com.mybatis.pojo.Employee\" autoMapping=\"true\">
            <result property=\"empMail\" column=\"email\" />
            <result property=\"dept.deptId\" column=\"deptId\"/>

        </resultMap>
    使用association 来设置级联属性
        --------------------------------------

    给java类型取别名
           <typeAliases>
                <typeAlias type=\"com.mybatis.pojo.Employee\" alias=\"Employee\"/>
            </typeAliases>
            <select id=\"getEmpById\" resultType=\"Employee\">
    为某个包下的所有类取别名 默认是类名首字母小写

    <typeAliases>
        <package name=\"com.mybatis.pojo\"></package>
    </typeAliases>

    <select id=\"getEmpById\" resultType=\"employee\">
          SELECT * FROM employee WHERE id= #{id}
    </select>
    但是会存在重名冲突
        可以使用注解 @Alias(\"\")来避免 但是要和package配合使用
        注意:不要和mybatis 已经定义好的重合、
        建议写全类名 结构清晰
-------------------------------------------------
别名处理器: TypeHandler<String> 来自定义java的类型和数据库的转换
并使用@mappedJdbcTypes(JdbcType.VARCHAR)
在全局配置文件中使用<typeHandler handler=\"全类名\">进行配置
-------------------------------------------------
mybatis 支持多环境配置
    <environment id=\"development\">
-------------------------------
多数据库支持
    在全局配置文件中:
            <data IdProvider type=\"DB_VENDOR\">
                <!-- 为不同的数据库厂商取别名-->
                <property name=\"MySQL\" value=\"mysql\"/>
                <property name=\"SQL Server\" value=\"sql server\"/>
            </data IdProvider>
    在映射文件中:
           告诉mybatis是哪个厂商
                <select id=\"getEmpById\" resultType=\"com.mybatis.pojo.Employee\" data Id=\"mysql\">

    注意:有顺序
-------------------------------------------------
mapmapper 标签:
    resource:引用类路径下的sql映射文件
    url:引用磁盘下的映射文件
    class:引用注册接口  接口名必须和映射文件名同名并且在同一个包里
    ---------------------------
    sql写在方法上
        @Select(\"select * from employee where id=#{id}\")
    public interface EmployeeMapper {
        @Select(\"select * from employee where id=#{id}\")
        public Employee getEmpById(Integer id);
    }
    <mappers>
        <mapper class=\"com.mybatis.mapper.EmployeeMapper\"/>
    </mappers>
 -----------------------------------
注意:sqlSession要手动提交  可以使用可以自动提交的sqlSession的构造方法

执行完后 将自动生成的主键 自动装配给bean的属性
        <insert id=\"addEmp\" parameterType=\"com.mybatis.pojo.Employee\"
                useGeneratedKeys=\"true\" keyProperty=\"id\">
            insert into employee(lase_name,email,gender) values(#{lastName},#{email},#{gender})
        </insert>
        public void addEmp(Employee employee);
        -----------------------------------
#{} 从map中取值 一个参数时#{随便都可以} 多个参数时key为param1...param2...
获取时#{param1},#{param2}
解决方法:使用注解指定key值 public Employee getEmpById(@Param(\"id\") Integer id);
获取时#{id}
可以传对象 从对象中取属性 #{对象中的属性名} 它会自动识别
使用Map 作为参数  #{key} 就是取出map中对应key的value
推荐 别写一个数据传输对象 TO

如果是Collection (List) 特殊处理 把传入的list封装在map中 Collection 的key就是collection
精确 List key就是list #{list[0]}

# 是预编译的形式PreparedStatement 而$取出的值直接拼装在sql语句中
# 可以防止sql注入
返回值类型为List时 :配置对应sql映射时 resultType并不是list 而是list当中的泛型

返回值为map 在接口对应方法上加@MapKey(\"对象属性名 主键\") resultType=\"对象\"

自定义结果集映射
resultMap:
        <!-- type为要为哪个对象自定义映射-->
        <resultMap id=\"MyEmp\" type=\"com.mybatis.pojo.Employee\">
            <!-- 指定主键列的封装规则-->
            <!-- 指定哪一列 对应的java属性-->
            <id column=\"id\" property=\"id\"/>
           <!-- 定义普通列-->
            <result column=\"last_name\" property=\"lastName\"/>
            <!-- 其他不指定的列会自动封装-->
            <result column=\"email\" property=\"email\"/>
            <result property=\"gender\" column=\"gender\"/>
        </resultMap>
        <!-- #{id}从传递过来的参数中取id值-->
        <select id=\"getEmpById\" resultMap=\"MyEmp\">
              SELECT * FROM employee WHERE id= #{id}
        </select>

----------------------
关联查询:
    resultMap:
        查出Employee时查出部门的信息
方法一:
        <resultMap id=\"EmpAndDept\" type=\"com.mybatis.pojo.Employee\">
            <id column=\"id\" property=\"id\"/>
            <result property=\"lastName\" column=\"last_name\"/>
            <result property=\"email\" column=\"email\"/>
            <result column=\"gender\" property=\"gender\"/>
            <result property=\"dept.id\" column=\"did\"/>
            <result column=\"dept_name\" property=\"dept.departmentName\"/>
        </resultMap>
        <select id=\"getEmpAndDept\" resultMap=\"EmpAndDept\">
            select e.id id,e.last_name last_name,e.email email,e.gender gender,e.d_id d_id,d.id did,d.dept_name dept_name from employee e,dept d where e.d_id = d.id AND e.id=#{id}
        </select>
方法二:
        <resultMap id=\"EmpAndDept\" type=\"com.mybatis.pojo.Employee\">
            <id column=\"id\" property=\"id\"/>
            <result property=\"lastName\" column=\"last_name\"/>
            <result property=\"email\" column=\"email\"/>
            <result column=\"gender\" property=\"gender\"/>
            <association property=\"dept\" javaType=\"com.mybatis.pojo.Department\">
                <id column=\"did\" property=\"id\"/>
                <result property=\"departmentName\" column=\"dept_name\"/>
            </association>
            <!--<result property=\"dept.id\" column=\"did\"/>-->
            <!--<result column=\"dept_name\" property=\"dept.departmentName\"/>-->
        </resultMap>
 -------------------------------------
 association 分步查询:
    <resultMap id=\"EmpAndDept\" type=\"com.mybatis.pojo.Employee\">
        <id column=\"id\" property=\"id\"/>
        <result property=\"lastName\" column=\"last_name\"/>
        <result property=\"email\" column=\"email\"/>
        <result column=\"gender\" property=\"gender\"/>
        <!--<association property=\"dept\" javaType=\"com.mybatis.pojo.Department\">-->
            <!--<id column=\"did\" property=\"id\"/>-->
            <!--<result property=\"departmentName\" column=\"dept_name\"/>-->
        <!--</association>-->
        <!--<result property=\"dept.id\" column=\"did\"/>-->
        <!--<result column=\"dept_name\" property=\"dept.departmentName\"/>-->
        <!--使用分步查询 查员工后 会有did 根据did查部门 column 指定将那一列的值传给这个方法-->
        <association property=\"dept\" select=\"com.mybatis.mapper.DepartmentMapper.getDepartmentById\" column=\"d_id\">
        </association>
    </resultMap>

    <select id=\"getEmpAndDept\" resultMap=\"EmpAndDept\">
        select * from employee where id=#{id}
    </select>
    ------------------------
    <mapper namespace=\"com.mybatis.mapper.DepartmentMapper\">
        <resultMap id=\"department\" type=\"com.mybatis.pojo.Department\">
            <id column=\"id\" property=\"id\"></id>
            <result property=\"departmentName\" column=\"dept_name\"/>
        </resultMap>
        <select id=\"getDepartmentById\" resultMap=\"department\">
            select * from dept where id=#{id}
        </select>

    </mapper>
    ------------------------------
    分布查询延迟加载:分步查询基础上加两个配置
    <settings>
        <setting name=\"lazyLoadingEnabled\" value=\"true\"/>
        <setting name=\"aggressiveLazyLoading\" value=\"false\"/>
    </settings>
    -------------------------
一对多:
    collection:
            <resultMap id=\"OneToMany\" type=\"com.mybatis.pojo.Department\">
                <id column=\"did\" property=\"id\"></id>
                <result property=\"departmentName\" column=\"dept_name\"/>
                <!--定义集合类型属性
                ofType 集合里元素的类型-->
                <collection property=\"emps\" ofType=\"com.mybatis.pojo.Employee\">
                    <id column=\"eid\" property=\"id\"/>
                    <result property=\"lastName\" column=\"last_name\"/>
                    <result column=\"email\" property=\"email\"/>
                    <result property=\"gender\" column=\"gender\"/>
                </collection>
            </resultMap>
            <select id=\"getDepartmentByIdPlus\" resultMap=\"OneToMany\">
                select d.id did,d.dept_name dept_name,e.id eid,e.last_name last_name,e.email email,e.gender gender from dept d left join employee e
                on d.id = e.id
                where d.id=#{id}
            </select>
            ---------------------
collection 分段查询
        <resultMap id=\"OneToMany\" type=\"com.mybatis.pojo.Department\">
            <id column=\"did\" property=\"id\"></id>
            <result property=\"departmentName\" column=\"dept_name\"/>
            <!--定义集合类型属性
            ofType 集合里元素的类型-->
            <!--<collection property=\"emps\" ofType=\"com.mybatis.pojo.Employee\">-->
                <!--<id column=\"eid\" property=\"id\"/>-->
                <!--<result property=\"lastName\" column=\"last_name\"/>-->
                <!--<result column=\"email\" property=\"email\"/>-->
                <!--<result property=\"gender\" column=\"gender\"/>-->
            <!--</collection>-->
            <collection property=\"emps\" select=\"com.mybatis.mapper.EmployeeMapper.getEmployeeByDeptId\" column=\"did\">

            </collection>
        </resultMap>
        <select id=\"getDepartmentByIdPlus\" resultMap=\"OneToMany\">
            select d.id did,d.dept_name dept_name from dept d
            where d.id=#{id}
        </select>
        传递一个值用 column 传递多个值 封装map传递:column=\"{key1=column1,...}\"
        column=\"{deptId=did}  fetchType=\"lazy\"懒加载
        -----------------------------
        鉴别器:
        <resultMap id=\"MyEmpDiscriminator\" type=\"com.mybatis.pojo.Employee\">
            <id column=\"id\" property=\"id\"/>
            <result property=\"lastName\" column=\"last_name\"/>
            <result property=\"email\" column=\"email\"/>
            <result column=\"gender\" property=\"gender\"/>
            <!--column 指定要判断哪列 javaType 就是列值对应的类型-->
            <discriminator javaType=\"string\" column=\"gender\">
                <!--0女生 1男生 resultType 指定封装的结果类型-->
                <case value=\"0\" resultType=\"com.mybatis.pojo.Employee\">
                    <association property=\"dept\" select=\"com.mybatis.mapper.DepartmentMapper.getDepartmentById\" column=\"d_id\">
                    </association>
                </case>
                <case value=\"1\"></case>
            </discriminator>
        </resultMap>
        ------------------------
动态SQL
    if:
            <select id=\"getEmployeeByIf\" resultType=\"com.mybatis.pojo.Employee\">
                select * from employee
                where
                <if test=\"id != null\">
                    id=#{id}
                </if>
                <if test=\"lastName != null and lastName != \'\'\">
                    and last_name like #{lastName}
                </if>
                <if test=\"email!=null and email.trim()!=\'\'\">
                    and email=#{email}
                </if>
                <if test=\"gender!=null\">
                    and gender=#{gender}
                </if>
            </select>
            如果没有id就会出错 会多出一个and
       解决方案:
            1、给where 后面加 1=1
            2、使用where标签 只会去掉第一个多出来的and
            3、使用trim标签
<trim prefix=\"\" prefixOverrides=\"\" suffix=\"\" suffixOverrides=\"\">
           prefix给拼完后的字符串加一个前缀
           prefixOverrides前缀覆盖
           suffix给字符串加一个后缀
           suffixOverides后缀覆盖
               <select id=\"getEmployeeByIf\" resultType=\"com.mybatis.pojo.Employee\">
                   select * from employee
           --
                   <trim prefix=\"where\"  prefixOverrides=\"and\" suffixOverrides=\"and\">
                       <if test=\"id != null\">
                           id=#{id}
                       </if>
                       <if test=\"lastName != null and lastName != \'\'\">
                           and last_name like #{lastName}
                       </if>
                       <if test=\"email!=null and email.trim()!=\'\'\">
                           and email=#{email}
                       </if>
                       <if test=\"gender!=null\">
                           and gender=#{gender}
                       </if>
                   </trim>
               </select>
     -------------------
choose when otherwise标签:
    <select id=\"getEmployeeByIf\" resultType=\"com.mybatis.pojo.Employee\">
        select * from employee
        <where>
            <choose>
                <when test=\"id != null\">
                    id=#{id}
                </when>
                <when test=\"lastName != null and lastName != \'\'\">
                  last_name like #{lastName}
                </when>
                <when test=\"email!=null and email.trim()!=\'\'\">
                    email=#{email}
                </when>
                <otherwise>
                    gender=#{gender}
                </otherwise>
            </choose>
        </where>
    </select>
    ---------------------------
   set标签
    <update id=\"updateEmp\">
        update employee
        <set>
            <if test=\"lastName!=null\">
                last_name=#{lastName},
            </if>
            <if test=\"email!=null\">
                email=#{email},
            </if>
        </set>
               where id=#{id}
    </update>
    ------------------
        <update id=\"updateEmp\">
            update employee

            <trim prefix=\"set\" suffixOverrides=\",\">
                <if test=\"lastName!=null\">
                    last_name=#{lastName},
                </if>
                <if test=\"email!=null\">
                    email=#{email},
                </if>
            </trim>
                   where id=#{id}
        </update>
        ----------------------
foreach 标签
    select * from employee
       <foreach collection=\"\" item=\"\" open=\"where id in (\" close=\")\" separator=\",\" >
        </foreach>
        ---------------
foreach 用于批量插入 遍历对象 对每一个item=\"emp\" #{emp.lastName}取值
-------------------------
两个内置参数:不只有方法传递过来的参数 它还有内置的参数
    :_parameter代表整个参数(单个时就是这个参数,多个时就是这个map)
      _data Id代表如果配置了Data IdProvider标签 代表它的别名
        在select标签中实验if标签判断 _data Id 调用不同的语句 来实现多数据库
-----------------------
数据绑定 <bind name=\"_lastName\" value=\"\'%\'+lastName+\'%\'\"> 后就可以使用#{_lastName}实现传参不用传%
抽取sql片段:
    <!--抽取可重用的sql片段-->
    <sql id=\"insertColumn\">
        id,last_name,email,#{test}

    </sql>
    <insert id=\"\">
        insert into employee(
          <include refid=\"insertColumn\">
              <property name=\"test\" value=\"abc\"></property>
          </include>
        )
        values (1,\"tt\",\"tt@qq.com\")
    </insert>
    ---------------------------

缓存:一级缓存:本地缓存

      二级缓存:全局缓存<setting name=\"cacheEnabled\" value=\"true\"/>
      <mapper namespace=\"com.mybatis.mapper.EmployeeMapper\">
          <!--使用二级缓存 POJO需要实现序列化接口-->
          <cache type=\"自定义缓存的全类名 实现Cache接口即可 例如ehcache的全类名\" blocking=\" \" eviction=\"缓存的回收策略\" flushInterval=\"缓存刷新间隔\" readOnly=\"是否只读\" size=\"存放多少元素\"/>
        <select useCache=\"true\">
      <mapper/>
      session关闭后 一级缓存的数据放入二级缓存 其他session可以获取 不要发语句

 

收藏 打印