MyBatis 持久层

一、#和$的区别

$接收的参数不经过处理直接拼接到SQL上,属于一种SQL注入,安全性较低,容易被成为攻击数据库的方式,常用于构建动态表名、动态列名、动态条件。#接收的参数会经过处理后转化成字符串,安全性高,常用于接收前端传到后端的SQL搜索条件。

二、动态SQL
新增操作,使用主键回填,回填到数据模型里的id属性
<insert id="insert" useGeneratedKeys="true" keyProperty="id"> 
    insert into system_user 
    <trim prefix="(" prefixOverrides="." suffix=")" suffixOverrides=",">
      .name, -> 添加前缀'(',删除前缀'.',添加后缀')',删除后缀','
    </trim>
    values (#{name})
</insert>
trim里的原始内容: .name,
prefix:给原始内容添加前缀'(' -> (.name,
prefixOverrides:给原始内容删除前缀'.' -> (name,
suffixOverrides:给原始内容删除后缀',' -> (name
suffix:给原始内容添加后缀')' -> (name)
prefixOverrides\suffixOverrides="AND|OR"; -> 删除可能性的前缀

删除操作
<delete id="delete" parameterType="com.wjx.SystemUser">
    delete from system_user where id = #{id}
</delete>

更新操作
<update id="update" parameterType="">
    update system_user
    <set> -> 自动清除多余的逗号,避免SQL语法错误
        <if test="name != null and name != '' ">
            name = #{name},
        </if>
    </set>
    where id = #{id}
</update>

数据映射集,column指数据库列名,property指数据模型属性名,名称相同可以不配置
查询语句会把结果存储到column中,通过映射关系,将结果设置到数据模型上
一对一或者一对多查询时,通过{key=value}的形式将传参通过column属性传递到子查询语句中
鉴别器根据某些条件决定级联的方案,例如根据性别获取人的体检信息
<resultMap id="BaseResultMap" type="com.wjx.SystemUser">
    <constructor> -> 配置数据模型的构造方法
      <idArg column="id" javaType="java.lang.Integer"/>
      <arg column="name" javaType="java.lang.String"/>
    </constructor>
    <id column="id" property="id" /> -> ID列,重复会删除多余的数据
    <result column="name" property="name" /> -> 普通数据字段列
    <association property="role" column="{uid=su.id}" select="role"/> -> 一对一
    <collection property="permission" column="id" /> -> 一对多
    <discriminator javaType="long" column="sex"> -> 鉴别器
      <case value="1" resultMap="male"/> -> 查询男性体检表
      <case value="0" resultMap="female"/> -> 查询女性体检表
    </discriminator>
</resultMap>

<resultMap id="male" type="com.wjx.male" extends="BaseResultMap">
    <association property="health" column="id" select="male"/>
    select * from health_male where user_id = #{id} -> 子查询(male)
</resultMap>

<resultMap id="female" type="com.wjx.female" extends="BaseResultMap">
    <association property="health" column="id" select="female"/>
    select * from health_female where user_id = #{id} -> 子查询(female)
</resultMap>

主查询语句
<select id="user" resultType="com.wjx.SystemUser">
    select * from system_user su
    <where> -> 当有条件成立才生成WHERE语句
        <if test="list.size() != 0">
            su.id in
            <foreach collection="list" index="index" item="id"
                     open="(" close=")" separator=","> -> 接收集合参数并循环遍历
                #{id}
            </foreach>
        </if>
        <if test="startTime != null">
            and su.create_time <![CDATA[ >= ]]> #{startTime} -> 大于等于
        </if>
        <if test="endTime != null">
            and su.create_time <![CDATA[ <= ]]> #{endTime} -> 小于等于
        </if>
        <choose>
            <when test="name != null and name != ''">
              and su.name = #{name}
            </when>
            <otherwise>
              and su.name is not null
            </otherwise>
        </choose>
    </where>
</select>

子查询语句
<select id="role" resultType="com.wjx.SystemRole">
    select sr.* from system_role sr
    inner join system_user_role sur on sur.role_id = sr.id
    where sur.user_id = #{uid}
</select>

SQL片段
<sql id="sql">
  id,name,sex
</sql>
select <include refid="sql"/> from system_user
三、存储过程
DROP PROCEDURE SCORE; -> MySQL

CREATE PROCEDURE SCORE(IN date VARCHAR(10)) -> 统计学生每次测验的总分
BEGIN
    DROP TABLE IF EXISTS provisionally;
    CREATE TEMPORARY TABLE provisionally
    (
        name VARCHAR(20),
        score INT(11),
        date VARCHAR(20)
    );
    INSERT INTO provisionally (name,score,date)
    SELECT student.name,SUM(exam.score),exam.date FROM student
    INNER JOIN exam ON student.id = exam.student_id
    GROUP BY student.name,exam.date;
    IF date IS NULL THEN 
        SELECT * FROM provisionally ORDER BY score DESC;
    ELSE
        SELECT * FROM provisionally WHERE provisionally.date = date
        ORDER BY score DESC;
    END IF;
END

CALL SCORE(null); -> 查出所有的信息

public interface StudentExamDao{ -> Mybatis
  List<LinkedHashMap<String, Object>> score(String date);
}

<select id="score" statementType="CALLABLE" resultType="java.util.LinkedHashMap">
    {CALL SCORE(#{date})};
</select>
@Results(id = "user", value = {
    @Result(column = "user_id", property = "userId")
})
@ResultType(value = User.class)
@Select("{call pkg_user.p_get_user(" +
    "#{in_user_id, jdbcType=NUMERIC, mode=IN}, " +
    "#{out_user, jdbcType=CURSOR, mode=OUT, resultMap=user}, " +
    "#{out_status, jdbcType=VARCHAR, mode=OUT}
")}")
@Options(statementType = StatementType.CALLABLE)
void getUser(HashMap<String, Object> map);
四、生成代码
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>1.2.4</version>
</dependency>

<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.3.5</version>
    <scope>compile</scope>
    <optional>true</optional>
</dependency>

mapper.not-empty=false
mapper.identity=MYSQL
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <context id="MysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

        <!--代码生成基类-->
        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <property name="mappers" value="springboot.wjx.generator.GeneratorMapper"/>
        </plugin>

        <!--数据库连接-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/springboot"
                        userId="root"
                        password="123456">
        </jdbcConnection>

        <!-- 对于生成的pojo所在包 -->
        <javaModelGenerator targetPackage="springboot.wjx.pojo" targetProject="src/main/java"/>

        <!-- 对于生成的mapper所在目录 -->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>

        <!-- 配置mapper对应的java映射 -->
        <javaClientGenerator targetPackage="springboot.wjx.mapper"
                             targetProject="src/main/java" type="XMLMAPPER"/>

        <!--生成代码的表-->
        <table tableName="user"></table>

    </context>
</generatorConfiguration>
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;

public interface GeneratorMapper<T> extends Mapper<T>, MySqlMapper<T> {
    // 特别注意,该接口不能被SpringBoot容器扫描,否则会报错
}

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

public class GeneratorApplication {
    public static void generator() throws Exception {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        //指定逆向工程配置文件
        File configFile = new File("generatorConfig.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }

    public static void main(String[] args) throws Exception {
        try {
            generator();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 分页插件及配置
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.3</version>
</dependency>

pagehelper.helper-dialect=mysql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
pagehelper.params=count=countSql
五、配置文件
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.1</version>
</dependency>

mybatis.type-aliases-package=springboot.wjx.pojo
mybatis.mapper-locations=classpath*:mapper/*.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>
    <settings> -> 输出运行日志
        <setting name="logImpl" value="SLF4J"/>
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <typeAliases> -> 定义别名
        <package name="com.wjx.pojo"/>
    </typeAliases>
</configuration>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容