Mybatis 从入门到精通---编程不良人

视频
https://www.bilibili.com/video/BV1EE411W7Q1
代码
https://github.com/wei198621/allTypes_persistence

mybatis 相关网站
MyBatis中文官网 http://www.mybatis.cn/
mybatis中文网 http://www.mybatis.org (202012不可以访问了,原因未知)

在这里插入图片描述

mybatis 简介

在这里插入图片描述

环境搭建

获取sqlSession

public class TestMybatis {

    public static void main(String[] args) throws SQLException, IOException {
      /*  //读取配置  方式一
        InputStream resourceAsStream = TestMybatis.class.getResourceAsStream("/mybatis-config.xml");
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);*/

        //Mybatis读取配置文件的方式
        Reader resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);

        SqlSession sqlSession = sessionFactory.openSession();
        System.out.println(sqlSession);
        //org.apache.ibatis.session.defaults.DefaultSqlSession@5a39699c
        sqlSession.getConnection().commit();
    }
}

执行查询

在这里插入图片描述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

mybatis 增删改

在这里插入图片描述https://www.bilibili.com/video/BV1EE411W7Q1?p=4
20201210 12

mybatis SQL进阶学习

Xml中的特殊字符

在这里插入图片描述

关于 jdbcType

全部的jdbcType属性
在这里插入图片描述

// 测试的时候,不写  ,jdbcType=INTEGER   也可以正常更细 Null  类型的值,可能是最新版本的mybatis 解决了陈老师讲解时间点2018年时候的问题(也可能是数据库原因,我测试库是mysql)
<update id="update" parameterType="Emp">
		update t_emp set name=#{name,jdbcType=VARCHAR},age=#{age,jdbcType=INTEGER},birthday=#{bir,jdbcType=DATE} where id=#{id}
	</update>

关于like

//like '%keyWords%'  ⇒   like '%'||#{keyWords}||'%'
<select id="selectByLike" parameterType="String" resultType="Emp">
		select id,name,age,birthday bir from t_emp where name like  '%'||#{keyWords}||'%'
	</select>

关于分页查询

	<select id="selectByPage"  resultType="Emp"> 
		<!-- < &lt;  > &gt;    <= &lt;=   >= &gt;= -->
		select e1.id,e1.name,e1.age,e1.bir from 
			(select e.id,e.name,e.age,e.birthday bir,rownum r from 
				(select id , name ,age , birthday from t_emp order by name) e
			where rownum &lt;= #{pageNow}*#{pageSize} ) e1 
		where r &gt;  (#{pageNow}-1)*#{pageSize}
	</select>

动态sql

sql标签 & include 标签

<!-- sql sql语句片段复用标签 
		id : 代表片段的唯一标识   (唯一)
	-->
	<sql id="commonFileds">
		 id,name,publishDate pubDate,price,author
	</sql>
	
	<select id="selectAll" parameterType="com.baizhi.entity.Book" resultType="com.baizhi.entity.Book">
		<!-- 
			include  使用外部的哪个sql片段
			refid   使用片段的id
		 -->
		select <include refid="commonFileds"/> from t_book
	</select>

if 标签 版本一

这样做
当 name author 都为空 sql 语句为 **** where 会报错
当前name为空 sql 语句为 **** where and author= 会报错

<!-- sql sql语句片段复用标签 
		id : 代表片段的唯一标识   (唯一)   	-->
	<sql id="commonFileds">
		 id,name,publishDate pubDate,price,author
	</sql>

<select id="selectByFields" parameterType="com.baizhi.entity.Book" resultType="com.baizhi.entity.Book">
		select <include refid="commonFileds"/> from t_book
		where 
			<if test="name!=null and name!=''">
				name = #{name}
			</if>
			<if test="author!=null and author!=''">
				and author = #{author}
			</if>	
	</select>

if 标签 版本二

<!-- sql sql语句片段复用标签 
		id : 代表片段的唯一标识   (唯一)   	-->
	<sql id="commonFileds">
		 id,name,publishDate pubDate,price,author
	</sql>

<select id="selectByFields" parameterType="com.baizhi.entity.Book" resultType="com.baizhi.entity.Book">
		select <include refid="commonFileds"/> from t_book
		where 1=1 
			<if test="name!=null and name!=''">
				and name = #{name}
			</if>
			<if test="author!=null and author!=''">
				and author = #{author}
			</if>	
	</select>

if 标签 版本三 (if标签 + where 标签)

<!-- sql sql语句片段复用标签 
		id : 代表片段的唯一标识   (唯一)   	-->
	<sql id="commonFileds">
		 id,name,publishDate pubDate,price,author
	</sql>

<select id="selectByFields" parameterType="com.baizhi.entity.Book" resultType="com.baizhi.entity.Book">
		select <include refid="commonFileds"/> from t_book
		<where>
			<if test="name!=null and name!=''">
				name = #{name}
			</if>
			<if test="author!=null and author!=''">
				and author = #{author}
			</if>
		</where>
	</select>

在这里插入图片描述

choose when 标签

// name price 都不为空 ,只执行第一个name ***的匹配

	<sql id="commonFileds">
		 id,name,publishDate pubDate,price,author
	</sql>

<select id="selectByChoose" parameterType="com.baizhi.entity.Book" resultType="com.baizhi.entity.Book">
		select <include refid="commonFileds"/> from t_book
		where
		<choose>
			<when test="name!=null and name!=''">
				name = #{name}
			</when>
			<when test="price!=null">
				price = #{price}
			</when>
			<otherwise>
				author = #{author}
			</otherwise>
		</choose>
	</select>

set 标签

// A code block
var foo = 'bar';

在这里插入图片描述在这里插入图片描述

trim 标签

<update id="update" parameterType="com.baizhi.entity.Book">
		update t_book 
			<!-- 
				prefix:加入前缀
				prefixOverrides:去掉前缀
				suffix:加入后缀
				suffixOverrides:去掉后缀
			 -->
			<trim prefix="set"  suffix="where" suffixOverrides=",">
				<if test="name!=null and name != ''">
					name = #{name},
				</if>
				<if test="author!=null and author != ''">
					author = #{author}
				</if>
			</trim>
			 id = #{id}
	</update>
 

在这里插入图片描述

foreach 批处理

---- 批处理 
BEGIN
	insert into t_book values('13','六脉神剑',sysdate,120.23,'小黑');
	insert into t_book values('14','如来神掌',sysdate,110.23,'小名');
	insert into t_book values('15','葵花宝典',sysdate,80.23,'无名');
	insert into t_book values('16','星星点灯',sysdate,90.34,'小牛');
	insert into t_book values('17','黯然销魂掌',sysdate,67.23,'小伟');
END;
	<insert id="insertAll" parameterType="list">
		BEGIN
			<!-- 
				collection:用来书写遍历集合类型
				index : 当前遍历的索引  从0 开始
				item  : 当前遍历元素的别名
				open  : 在第一遍历之前加入的语句
				close : 在最后一个次遍历之后加入的语句
				separator: 在每一次遍历之后加入的语句   最后一次不加入
			 -->
			<foreach collection="list" close=";" index="i" item="book" separator=";">
				insert into t_book values(#{book.id},#{book.name},#{book.pubDate},#{i},#{book.author})
			</foreach>
		
		END;
	</insert>

关联关系 一对一

数据库关系描述 : 用户表 user 与 身份信息表 card 是一对一的关系 ,数据库中可以在user表中加入外键cardid 引用 card 表,也可以在card表中加入user表id,作为外键。现实操作中我没有使用外键的习惯,(不清楚是好是坏)
代码中类描述: 可以如下,在User类中加入Card类,也可以在Card 类中引入 User ,

public class User {	
	private String id;
	private String name;
	private Integer age;
	private Date bir;	
	private Card card;//关系属性  不要出现在toString方法里面  	
}	

当SQL结果集,不是java代码中的对象时候, 用resultMap 替换resultType
association 处理一对一关系

<?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="com.baizhi.dao.UserDAO">
	<!-- 
		处理关联关系时  resultType无法将关系属性进行自动封装     只能处理单表简单类型(对象)
		
		处理关系属性赋值 :使用resultMap
			type:封装对象类型  如果是一个 直接写对象的全名(别名)  如果是多个 同样写泛型的类型
			id : resultMap的名字
	 -->
	 
	 
	 <resultMap type="com.baizhi.entity.User" id="aaa">
	 	<!-- 用来封装user中的主键的值 column 数据库返回的列名   property 类中属性名 -->
	 	<id column="userId" property="id"/>
	 	<!-- 用来封装user中的普通属性值 -->
	 	<result column="name" property="name"/>
	 	<result column="age" property="age"/>
	 	<result column="bir" property="bir"/>
	 	<!-- 关系属性封装 一对一  对象类型
	 		association: 用来处理一对一关系属性封装
	 		property : 关系属性名
	 		javaType: 关系属性的类型
	 	 -->
	 	<association property="card" javaType="com.baizhi.entity.Card" >
	 		<id column="cardId" property="id" />
	 		<result column="no" property="no"/>
	 		<result column="address" property="address"/>
	 		<result column="fork" property="fork"/>
	 	</association>
	 </resultMap>

	<!-- 
		resultMap: 封装对象时使用外部的哪个resultMap进行封装  书写resultMap标签的id属性
	 -->
	<select id="queryAll" resultMap="aaa">
		select u.id userId,u.name,u.age,u.bir,
		       c.id cardId,c.no,c.fork,c.address 
		from t_users u 
		left join t_card c 
		on  u.cardId = c.id
	</select>
	
	
	
  
</mapper>


//关系属性 不要出现在toString方法里面
如果 User.Card Card.User 相互出现在彼此的toString方法里面, 当打印某个toString方法时候,会形成回环,造成栈溢出,稍后试试
在这里插入图片描述
视频地址 – 编程不良人
https://www.bilibili.com/video/BV1EE411W7Q1?p=10

<?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="com.tiza.leo.mybatis_baizhi02_complex.dao.BookDAO">
    <sql id="commonFields">
        id,name,publishDate pubDate,price,author
    </sql>

    <select id="selectAll" parameterType="com.tiza.leo.mybatis_baizhi02_complex.entity.Book" resultType="com.tiza.leo.mybatis_baizhi02_complex.entity.Book">
        select <include refid="commonFields"/> from mybatis_baizhi_book
    </select>

    <select id="selectByFields" parameterType="com.tiza.leo.mybatis_baizhi02_complex.entity.Book" resultType="com.tiza.leo.mybatis_baizhi02_complex.entity.Book">
        select <include refid="commonFields"/> from mybatis_baizhi_book
        <where>
            <if test="name!=null and name!=''">
                name = #{name}
            </if>
            <if test="author!=null and author!=''">
                and author = #{author}
            </if>
        </where>
    </select>


    <select id="selectByChoose" parameterType="com.tiza.leo.mybatis_baizhi02_complex.entity.Book" resultType="com.tiza.leo.mybatis_baizhi02_complex.entity.Book">
        select <include refid="commonFields"/> from mybatis_baizhi_book
        WHERE
        <choose>
            <when test="name!=null and name!=''">
                name=#{name}
            </when>
            <when test="price!=null">
                price=#{price}
            </when>
            <otherwise>
                author=#{author}
            </otherwise>
        </choose>
    </select>

    <update id="update" parameterType="com.tiza.leo.mybatis_baizhi02_complex.entity.Book">
        update mybatis_baizhi_book
        <trim prefix="set" suffix="where" suffixOverrides=",">
            <if test="name!=null and name!=''">
                name=#{name}
            </if>
            <if test="author!=null and author!=''">
                author =#{author},
            </if>
        </trim>
        id=#{id}
    </update>



 <!--    * mysql  测试没有通过 在local zhan comp
     * oracle 没有测试
     *
     * 一致 mysql 不支持  begin  end 批量处理语法 -->
    <insert id="insertAll" parameterType="list">
        BEGIN
        <!--
            collection:用来书写遍历集合类型
            index : 当前遍历的索引  从0 开始
            item  : 当前遍历元素的别名
            open  : 在第一遍历之前加入的语句
            close : 在最后一个次遍历之后加入的语句
            separator: 在每一次遍历之后加入的语句   最后一次不加入
         -->
        <foreach collection="list" close=";" index="i" item="book" separator=";">
            insert into mybatis_baizhi_book values(#{book.id},#{book.name},#{book.pubDate},#{i},#{book.author})
        </foreach>
        END;
    </insert>

</mapper>

关联关系 一对多

// A code block
var foo = 'bar';

在这里插入图片描述

在这里插入图片描述

关联关系 多对多

学生与课程的关系是多对多 (通过选课表关联)
代码
https://github.com/wei198621/allTypes_persistence


/**
 * @author leowei
 * @date 2020/12/13  - 10:01
 */
public class Student {
    private String id;
    private String name;
    private Integer age;
    private List<Course> courses;//关系属性   用来表示一个学生选了多个课程
    }
/**
 * @author leowei
 * @date 2020/12/13  - 10:01
 */
public class Course {
    private String id;
    private String name;
    }

/**
 * @author leowei
 * @date 2020/12/13  - 13:19
 */
public interface StudentDAO {
    public List<Student> queryAll();
}
<?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="com.tiza.leo._05mybatis_baizhi03_complex_plus.dao.StudentDAO">
    <resultMap id="studentMap" type="com.tiza.leo._05mybatis_baizhi03_complex_plus.entity.Student">
        <id column="id" property="id" />
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <!-- 封装课程信息 一对多   collection类型 -->
        <collection property="courses" javaType="list" ofType="com.tiza.leo._05mybatis_baizhi03_complex_plus.entity.Course">
            <id column="cid" property="id"/>
            <result column="cname" property="name"/>
        </collection>
    </resultMap>

    <select id="queryAll" resultMap="studentMap">
        select s.id,s.name,s.age,
        c.id cid,c.name cname
        from mybatis_baizhi_student s
        left join mybatis_baizhi_student_course sc          on s.id = sc.sid
        left join mybatis_baizhi_course c          on sc.cid = c.id
    </select>


</mapper>

package com.tiza.leo._05mybatis_baizhi03_complex_plus.test;

import com.tiza.leo._05mybatis_baizhi03_complex_plus.dao.StudentDAO;
import com.tiza.leo._05mybatis_baizhi03_complex_plus.entity.Course;
import com.tiza.leo._05mybatis_baizhi03_complex_plus.entity.Student;
import com.tiza.leo._05mybatis_baizhi03_complex_plus.util.MybatisUtil;

import java.util.List;

/**
 * @author leowei
 * @date 2020/12/13  - 13:25
 */
public class TestStudentDAO {
    public static void main(String[] args) {
        StudentDAO mapper = MybatisUtil.getSqlSession().getMapper(StudentDAO.class);
        List<Student> students = mapper.queryAll();
        for (Student student : students) {
            System.out.println("student = " + student);
            List<Course> courses = student.getCourses();
            for (Course cours : courses) {
                System.out.println("cours = " + cours);
            }
            System.out.println("===================================================");
        }
    }
}

MyBatis 通过包含的jdbcType类型

在这里插入图片描述

BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED
TINYINT REAL VARCHAR BINARY BLOB NVARCHAR
SMALLINT DOUBLE LONGVARCHAR VARBINARY CLOB NCHAR
INTEGER NUMERIC DATE LONGVARBINARY BOOLEAN NCLOB
BIGINT DECIMAL TIME NULL CURSOR

Mybatis中javaType和jdbcType对应和CRUD例子

//column 列名
<resultMap type="java.util.Map" id="resultjcm">
  <result property="FldNumber" column="FLD_NUMBER" javaType="double" jdbcType="NUMERIC"/>
  <result property="FldVarchar" column="FLD_VARCHAR" javaType="string" jdbcType="VARCHAR"/>
  <result property="FldDate" column="FLD_DATE" javaType="java.sql.Date" jdbcType="DATE"/>
  <result property="FldInteger" column="FLD_INTEGER"  javaType="int" jdbcType="INTEGER"/>
  <result property="FldDouble" column="FLD_DOUBLE"  javaType="double" jdbcType="DOUBLE"/>
  <result property="FldLong" column="FLD_LONG"  javaType="long" jdbcType="INTEGER"/>
  <result property="FldChar" column="FLD_CHAR"  javaType="string" jdbcType="CHAR"/>
  <result property="FldBlob" column="FLD_BLOB"  javaType="Blob" jdbcType="BLOB" />
  <result property="FldClob" column="FLD_CLOB"  javaType="string" jdbcType="CLOB"/>
  <result property="FldFloat" column="FLD_FLOAT"  javaType="float" jdbcType="FLOAT"/>
  <result property="FldTimeStamp" column="FLD_TIMESTAMP" javaType="java.sql.Timestamp" jdbcType="TIMESTAMP"/>
 </resultMap>

Mybatis中javaType和jdbcType对应关系

    JDBCType            JavaType
    CHAR                String
    VARCHAR             String
    LONGVARCHAR         String
    NUMERIC             java.math.BigDecimal
    DECIMAL             java.math.BigDecimal
    BIT                 boolean
    BOOLEAN             boolean
    TINYINT             byte
    SMALLINT            short
    INTEGER             int
    BIGINT              long
    REAL                float
    FLOAT               double
    DOUBLE              double
    BINARY              byte[]
    VARBINARY           byte[]
    LONGVARBINARY       byte[]
    DATE                java.sql.Date
    TIME                java.sql.Time
    TIMESTAMP           java.sql.Timestamp
    CLOB                Clob
    BLOB                Blob
    ARRAY               Array
    DISTINCT            mapping of underlying type
    STRUCT              Struct
    REF                 Ref
    DATALINK            java.net.URL[color=red][/color]

配置logback打印SQL日志

恰好我的环境跟这位兄台的一直,所以 参考文章 :
https://blog.csdn.net/u012489412/article/details/86691611

我的配置

我当前的springboot版本2.1.2.RELEASE
myabtis版本为3.5.0
logback版本为1.2.3

开始配置
1.在application.yml里面添加logback-spring.xml配置

下面是我的logback.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="1 seconds">

    <contextName>logback</contextName>
    <!--定义参数,后面可以通过${app.name}使用-->
    <property name="app.name" value="logback_test"/>
    <!--logback方式打印日志的目录地址-->
    <property name="scheduler.manager.server.home" value="log_logback"></property>
    <!--ConsoleAppender 用于在屏幕上输出日志-->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--定义了一个过滤器,在LEVEL之下的日志输出不会被打印出来-->
        <!--这里定义了DEBUG,也就是控制台不会输出比ERROR级别小的日志 即DEBUG,INFO,WARN,ERROR,FATAL;  -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>即DEBUG</level>
        </filter>
        <!-- encoder 默认配置为PatternLayoutEncoder -->
        <!--定义控制台输出格式-->
        <encoder>
            <pattern>%d [%thread] %-5level %logger{36} [%file : %line] - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--定义日志输出的路径-->
        <!--这里的scheduler.manager.server.home 没有在上面的配置中设定,所以会使用java启动时配置的值-->
        <!--比如通过 java -Dscheduler.manager.server.home=/path/to XXXX 配置该属性-->
        <file>${scheduler.manager.server.home}/logs/${app.name}.log</file>
        <!--定义日志滚动的策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--定义文件滚动时的文件名的格式-->
            <fileNamePattern>${scheduler.manager.server.home}/logs/${app.name}.%d{yyyy-MM-dd.HH}.log.gz
            </fileNamePattern>
            <!--60天的时间周期,日志量最大20GB-->
            <maxHistory>60</maxHistory>
            <!-- 该属性在 1.1.6版本后 才开始支持-->
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <!--每个日志文件最大100MB-->
            <maxFileSize>100MB</maxFileSize>
        </triggeringPolicy>
        <!--定义输出格式-->
        <encoder>
            <pattern>%d [%thread] %-5level %logger{36} [%file : %line] - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!--这个一定要 -->
    <logger name="com.tiza.xcmg.syncVehDataFromCrm.mapper" level="DEBUG" ></logger>

    <!--root是默认的logger 这里设定输出级别是debug-->
    <root level="ERROR">
        <!--定义了两个appender,日志会通过往这两个appender里面写-->
        <appender-ref ref="stdout"/>
        <appender-ref ref="file"/>
    </root>
    
</configuration>

关于这里,有两点想说明,
第一点:需要添加logger

 <!--这个一定要 -->
    <logger name="com.tiza.xcmg.syncVehDataFromCrm.mapper" level="DEBUG" ></logger>

第二点:root的level为INFO,这里使用debug也可以打印日志,但是日志太多,看起来头疼。也不方便有问题时查找问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值