Mybatis框架

Mybatis


日志介绍
日志级别

OFF<FATAL<ERROR<WARN<INFO<DEBUG<ALL

右边的级别包含左边的全部日志

日志配置
log4j.rootCategory=DEBUG, stdout , R
 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
 
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=F://mybatis.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
ORM介绍

Orm框架:完成数据库表与Javabean对象关系映射的框架就叫orm框架

JDBC:过程太麻烦,orm框架对原始jdbc过程进行封装

常见orm框架

  • Mybatis:用得多
  • Hibernate:用得少,学习成本高 40-50% 老的管理项目,趋于淘汰
  • Springjdbc:(用得少)
Mybatis入门

原名ibatis

mybatis将java代码和sql语句解耦合,将sql语句嵌入到xml配置文件中

1.引入jar包
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.16</version>
</dependency>
2.实体类
package cn.cdqf.entity;

import java.io.Serializable;

public class User implements Serializable {

    private String uname;

    private int uid;

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    @Override
    public String toString() {
        return "User{" +
                "uname='" + uname + '\'' +
                ", uid=" + uid +
                '}';
    }
}
3.dao层
public interface UserDao2 {
    List<User> queryAll();

    User queryByName(@Param("uname") String uname);

    User queryByName2(@Param("user") User uname);

    void insert(@Param("user") User user);

    void insert2(@Param("user") User user);

    //根据名称模糊查询 根据年龄范围查询
    List<User> queryByNameAndAge(@Param("uname") String uname,@Param("age") int age);
}
package cn.cdqf.dao.impl;

import cn.cdqf.dao.UserDao;
import cn.cdqf.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class UserDaoImpl implements UserDao {
    public List<User> queryAll() {
        //构造者模式 build  :构建工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //把配置文件转成输入流
        InputStream resourceAsStream = UserDaoImpl.class.getResourceAsStream("/mybatis-config.xml");
        //UserDaoImpl.class.getClassLoader().getResourceAsStream()
        //所有的构造者模式,有个方法build方法
        //工厂模式:造类  创建对象
        SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
        //拿数据库连接对象  connection  mybatis改名为SqlSession
        SqlSession sqlSession = build.openSession();
        List<User> objects = sqlSession.selectList("cn.cdqf.dao.UserDao.queryAll");
        //关闭资源
        sqlSession.close();
        return objects;
    }
}
4.主配置文件
<?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>
</configuration>
<?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="jdbc.properties"></properties>
    <typeAliases>
        <!--简写 实体类-->
        <package name="cn.cdqf.entity"></package>
    </typeAliases>
    <!--编码环境:Development、Test、Product-->
    <!--
        prod:生产环境,真实上线  运维
        test:测试环境   测试部门
        dev:开发环境   开发
    -->
    <environments default="development">
        <environment id="development">
            <!--事务配置-->
            <transactionManager type="JDBC"/>
            <!--数据源连接池配置-->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--指定mapper配置文件-->
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>
5.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">
<!--
    namespace:来区分当前项目中唯一的一个mapper.xml,一般用接口全路径来标识
-->
<mapper namespace="cn.cdqf.dao.UserDao">


</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">
<!--
    namespace:来区分当前项目中唯一的一个mapper.xml,一般用接口全路径来标识
-->
<mapper namespace="cn.cdqf.dao.UserDao">
    <!--
        id:对应接口中的方法名 id是唯一标识 不会重复
        resultType:指定当前查询的返回值,返回值只需要指定集合里面的内容,mybatis会根据sql返回条数自动判断是集合还是单个对象

        select:执行体 statement
    -->
    <select id="queryAll" resultType="cn.cdqf.entity.User">
        select * from user_a
    </select>
    <!--
    parameterType:指定参数类型
    -->
    <select id="queryByName" resultType="User" parameterType="string">
    <!--#{名字要跟接口方法中@param注解中指定名字相同}
        ......where uname=?   preparedStatemenet:会把传递字符串参数来的参数加""
        预编译平台,防止sql注入
        select * from user_a where uname="张三"
        "'张三' or 1=1"参数
        delete from user_a where uname='张三' or 1=1

        delete from user_a where uname="'张三' or 1=1" 预编译平台
    -->
        select * from user_a where uname=#{uname}
    </select>
    <select id="queryByName2" resultType="user" parameterType="user">
    <!--
            $会直接取 传过来对象参数的属性
    -->
        select * from user_a where uname='${uname}'
    </select>

    <insert id="insert" parameterType="user">
        insert into user_a(uid,uname) values(#{uid},#{uname})
    </insert>
    <!--
        插入的时候获得主键id
        1.在insert标签 指定下面三个属性
        useGeneratedKeys="true"
        keyColumn="uid":指定数据库字段
        keyProperty="uid":java对象的字段
         2.在insert内部加入如下代码
        <selectKey keyProperty="uid" keyColumn="uid" resultType="int">
            select last_insert_id();
        </selectKey>
    -->
    <insert id="insert2" parameterType="user">
        insert into user_a(uname) values(#{uname})
    </insert>
</mapper>
$和#的区别(重点)

取参数

  • #采用预编译方式,会将传入的字符串用双引号引起,防止sqk注入
  • 直 接 将 值 取 出 , 不 能 防 止 s q l 注 入 , 而 且 直接将值取出,不能防止sql注入,而且 ,sql,只能接受对象参数

但若涉及到为sql传参以外的sql,如果需要java传递,就必须用**$**取

自定义工具类
package cn.cdqf.util;

import cn.cdqf.dao.impl.UserDaoImpl;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public enum  MyBatisUtil {
    INSTANCE;//就是当前类的对象 并且是单例

    private static final SqlSessionFactory sqlSessionFactory;

    static{
        //构造者模式 build  :构建工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //把配置文件转成输入流
        InputStream resourceAsStream = UserDaoImpl.class.getResourceAsStream("/mybatis-config.xml");
        //UserDaoImpl.class.getClassLoader().getResourceAsStream()
        //所有的构造者模式,有个方法build方法
        //工厂模式:造类  创建对象
        sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
    }
    //获取连接
    public SqlSession getSqlSession(){
        return  sqlSessionFactory.openSession();
    }
    //关闭连接
    public void close(SqlSession sqlSession){
        if(sqlSession!=null)
            sqlSession.close();
    }
    //提交事务
    public void commit(SqlSession sqlSession){
        if(sqlSession!=null)
            sqlSession.commit();//重要,否则更新类型的sql无法同步到数据库
        close(sqlSession);
    }
    //回滚事务
    public void rollback(SqlSession sqlSession){
        if(sqlSession!=null)
            sqlSession.rollback();
        close(sqlSession);
    }
}
主键返回
<!--
插入的时候获得主键id
-->
1.在insert标签 指定下面三个属性
useGeneratedKeys="true"
keyColumn="uid":指定数据库字段
keyProperty="uid":java对象的字段

 2.在insert内部加入如下代码
<selectKey keyProperty="uid" keyColumn="uid" resultType="int">
    select last_insert_id();
</selectKey>
动态代理实现

必须满足的条件

  1. 通过公共接口调用
  2. mapper.xml中的namespace必须是接口的全限定名
  3. mapper.xml中的id必须和接口中的方法名一致
安装Free Mybatis plugin插件
多参数 转义<![CDATA[]]> 模糊查询

多个不同类型的参数,parameterType就不写

<select id="queryByNameAndAge" resultType="cn.cdqf.entity.User">
    <![CDATA[
    select * from user_a where uname like concat("%",#{uname},"%")
    and age < #{age}
    ]]>
</select>
动态Sql
1.if
<!--判断名字不为null 且不为""-->
<if test="uname!=null and uname!=''">
    where uname like concat("%",#{uname},"%")
</if>
<if test="age!=null and age>0">
    and age>#{age}
</if>
2.where

自动去掉第一个and

 <select id="selectUserByIdAndName" resultType="com.edu.entity.User">
        select * from users
  		 <where>
            <if test="name!=null and name !=''">
                    and username like concat("%",#{name},"%")   
            </if>
            <if test="id != 0">
                    and id > #{id}
            </if>
     </where>
</select>
3.set

自动去掉最后一个","

<update id="update">
        <if test="map != null">
            update users
           <set>
                <foreach collection="map" index="key" item="value">
                    ${key} = #{value},
                </foreach>
           </set>
            where id = #{id}
        </if>
    </update>
4.trim
<update id="update">
        <if test="map != null">
            update users
            <!--prefix:前缀 suffixOverrides:覆盖最后的标记-->
            <trim prefix="set" suffixOverrides=",">
                <foreach collection="map" index="key" item="value">
                    ${key} = #{value},
                </foreach>
            </trim>
            where id = #{id}
        </if>
    </update>
5.choose when otherwise

互斥

  <select id="selectUserByIdAndName" resultType="com.edu.entity.User">
        <bind name="selectStr" value="'%'+name+'%'"/>
        select * from users
        <trim prefix="where" prefixOverrides="and">
            <choose>
                <when test="name!=null and name !=''">
                    username like #{selectStr}
                </when>
                <otherwise>
                    and id > #{id}
                </otherwise>
            </choose>
        </trim>
    </select>
6.bind(如上)
7.sql include
</select>
    <sql id="useSql">
    users
</sql>
    <select id="selectUserById" resultMap="UserMap" parameterType="int">
            select * from
        <include refid="useSql"></include>
             where id = #{id}
    </select>
8.foreach 数组 集合
 <update id="update">
        <if test="map != null">
            update users
            <trim prefix="set" suffixOverrides=",">
                <!--collection:接口中@Param定义的参数名
								若未定义,array:数组,maps:Map
				-->
                <foreach collection="map" index="key" item="value">
                    ${key} = #{value},
                </foreach>
            </trim>
            where id = #{id}
        </if>
    </update>
resultMap
<!--
    反射设置值,根据数据库列名 来获得属性名
    1.改别名(跟属性名相同)
    cdqf_tid tid,cdqf_tname tname
    2.通过resultMap映射
-->
<resultMap id="baseMap" type="Teacher">
    <!--
        type="Teacher":属性类型
        column:查询出来的列名
        property:类中属性名
    -->
    <id column="cdqf_tid" property="tid"></id>
    <result column="cdqf_tname" property="tname"></result>
</resultMap>
<sql id="baseSql">
    cdqf_tid,cdqf_tname
</sql>
<select id="queryAll" resultMap="baseMap">
    select
     <include refid="baseSql"></include>
     from cdqf_teacher
</select>
一对一
  1. 连表查询

    <resultMap id="baseMap" type="Student">
        <id column="cdqf_sid" property="sid"></id>
        <result column="cdqf_sname" property="sname"></result>
        <!--
            映射一对一关系
            property:属性名
            javaType:当前属性的类型
        -->
        <association property="teacher" javaType="Teacher">
            <id column="cdqf_tid" property="tid"></id>
            <result column="cdqf_tname" property="tname"></result>
        </association>
    </resultMap>
    
    <select id="queryAll" resultMap="baseMap">
    
        SELECT  cdqf_sid,cdqf_sname,cdqf_tname,cdqf_tid
        FROM cdqf_student s JOIN cdqf_teacher t
                                 ON s.`tid`=t.`cdqf_tid`
    
    </select>
    
  2. 接口调用

     <resultMap id="UserMap" type="user">
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="password" column="password"/>
            <result property="tel" column="tel"/>
            <result property="createTime" column="createTime"/>
         
         <!--columu属性将参数传到调用的接口方法中执行查询-->
            <association property="power" column="power"  javaType="Permission" select="com.edu.dao.PowerDao.queryPowerById" >
            </association>
        </resultMap>
        <select id="selectAll" resultMap="UserMap">
        select * from users
      </select>
    
一对多
  1. 连表查询

    <resultMap id="baseMap" type="Teacher">
        <!--
            type="Teacher":属性类型
            column:查询出来的列名
            property:类中属性名
        -->
        <id column="cdqf_tid" property="tid"></id>
        <result column="cdqf_tname" property="tname"></result>
        <!--ofType:集合元素得类型
        -->
        <collection property="studentList" ofType="Student">
            <id column="cdqf_sid" property="sid"></id>
            <result column="cdqf_sname" property="sname"></result>
        </collection>
    </resultMap>
    <sql id="baseSql">
        cdqf_tid,cdqf_tname
    </sql>
    <select id="queryAll" resultMap="baseMap">
        SELECT
            cdqf_tid,cdqf_tname,cdqf_sid,cdqf_sname
        FROM cdqf_teacher t  JOIN cdqf_student s
                                  ON t.`cdqf_tid`=s.`tid`
    </select>
    
  2. 接口调用

    <resultMap id="Power" type="Permission">
            <id property="id" column="id"/>
            <result property="right" column="right_value"/>
        
        <!--columu属性将参数传到调用的接口方法中执行查询-->
            <collection property="users" column="id" ofType="User" select="com.edu.dao.UserDao.selectUserById">
            </collection>
        </resultMap>
        <select id="queryAllPower" resultMap="Power">
            select * from permission
        </select>
    
延迟加载
 <settings>
        <setting name ="aggressiveLazyLoading" value="false"/>
        <!--开启延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
一二级缓存
<setting name="localCacheScope" value="SESSION"/>
<setting name="cacheEnabled" value="true"/>
<cache/>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值