Mybatis入门笔记


前言

我还没学SQL和JDBC怎么办,被迫来学Mybatis......

当然了如果各位看官有什么莫名其妙的报错的话,可以私信我,我如果会的话会尽量回复的(/doge)


一、简介

1.什么是Mybatis

  1. MyBatis 是一款优秀的持久层框架
  2. 它支持自定义 SQL、存储过程以及高级映射。
  3. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  4. MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

2.为什么用Mybatis

就是因为方便,传统的JDBC代码太复杂了。

二、配置环境

1.mybatis-config.xml

首先先认识一下配置文件

configuration(配置)
    properties(属性)
    settings(设置)
    typeAliases(类型别名)
    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)
    environments(环境配置)
    	environment(环境变量)
    		transactionManager(事务管理器)
    		dataSource(数据源)
    databaseIdProvider(数据库厂商标识)
    mappers(映射器)
  1. properties:我们可以通过properties属性来实现引用配置文件(方便后期修改)
  2. settings:调整设置
  3. typeAliases:降低冗余的全限定类名书写
  4. environments:可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境
  5. mappers:每一个Mapper.xml都需要在MyBatis核心配置文件中注册

2.第一个Mybatis

  1. 创建一个普通的maven项目

  2. pom.xml导入基础依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>sql_test</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
    
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.2</version>
            </dependency>
    
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
    
            <!--mql驱动-->
            <dependency>
                 <groupId>mysql</groupId>
                 <artifactId>mysql-connector-java</artifactId>
                <version>5.1.46</version>
           </dependency>
       </dependencies>
       
       <!--防止Maven资源导出错误问题-->
       <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
       </build>
    
        <properties>
            <maven.compiler.source>16</maven.compiler.source>
            <maven.compiler.target>16</maven.compiler.target>
        </properties>
    </project>
    
  3. 在resources目录下创建db.properties,写入连接数据库内容

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306?useSSL=false&useUnicode=true&characterEncoding=UTF-8
    username=root
    password=*****
    
  4. 在resources目录下创建mybatis-config.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>
        <properties resource="db.properties"/>
        
        <settings>
            <!--使用自定义logback+slf4j-->
            <setting name="logPrefix" value="" />
            <!--默认使用log4j-->
            <!-- <setting name="logImpl" value="LOG4J"/> -->
        </settings>
        
    	<!--别名-->
        <typeAliases>
            <typeAlias type="pojo.User" alias="User"/>
            <!-- <package name="pojo"/> 别名默认为包内类名的首字母小写 -->
        </typeAliases>
    
        <!--环境配置-->
        <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>
        
        <!--每一个Mapper.xml都需要在核心配置文件注册-->
        <mappers>
            <mapper resource="DAO/UserMapper.xml"/>
            <!--<mapper class="Dao.UserMapper"/>   -->
            <!--<package name="Dao"/>   使用包名扫描注册-->
        </mappers>
    </configuration>
    
  5. 创建工具类 mybatisUtils.java

    public class mybatisUtils {
    
        private static SqlSessionFactory sqlSessionFactory;
    
        static {
            try {
            	//SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建一个实例
            	//具体内容请百度搜索"工厂模式"和"单例模式"
                Reader resource = Resources.getResourceAsReader("mybatis-config.xml");
                //SqlSessionFactoryBuilder  一旦创建了SqlSessionFactory,就没用了
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(resource);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static SqlSession getSqlSession() {
            //参数为是否自动提交事务 其中增删改一定要提交事务,否则改动无效
            //SqlSession 的实例不是线程安全的,因此是不能被共享的
            return sqlSessionFactory.openSession(true);
        }
    
    }
    
  6. 创建Dao接口类 UserMapper.java

    public interface UserMapper {
    	 public List<User> getUserList();
    }
    
  7. 创建接口实现类 UserMapper.xml,每一个接口类里的函数都要在这里实现,并且一一对应

    <?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绑定一个指定的Dao接口-->
    <mapper namespace="pojo.UserMapper">
        <select id="getUserList" resultType="pojo.User">
        select * from USER
      </select>
    </mapper>
    
  8. 创建测试类

        @Test
        public void test(){
            //获得sqlSession对象
            SqlSession sqlSession = tools.getSqlSession();
            //执行SQL
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            //操作数据库
            User user = mapper.getbyId3(1, "a");
            //输出
            System.out.println(user);
    
            //关闭
            sqlSession.close();
        }
    
  9. 最终项目图
    在这里插入图片描述

三、语法

1.CRUD

    <!--对于多参数的情况:-->
    <!--1.map 里面插入参数-->
    <select id="getbyId" parameterType="map" resultType="pojo.User">
        select * from mybatis.user where id=#{map_id} and name=#{map_name}
    </select>
	<!--2.注解-->
	<!--基本类型或者String需要加,其他引用类型不需要-->
	<!--User getbyId(@Param("p_id") int id,@Param("p_name") String name);-->
	<select id="getbyId" resultType="pojo.User">
        select * from mybatis.user where id = #{p_id} and name = #{p_name};
    </select>

    <!--増-->
    <insert id="addUser" parameterType="map">
        insert into mybatis.user (id, name, pwd)
        values (#{newid}, #{newname}, #{newpwd});
    </insert>
    <!--改-->
    <update id="updateUser" parameterType="pojo.User">
        update mybatis.user
        set name=#{name},
            pwd=#{pwd}
        where id = #{id};
    </update>
    <!--删-->
    <delete id="delUser" parameterType="int">
        delete
        from mybatis.user
        where id = #{id};
    </delete>

    <!--模糊查询  防止sql注入-->
    <select id="getUserLike" parameterType="map" resultType="pojo.User">
        select * from mybatis.user where name like "%"#{map_name}"%";
    </select>
    
    <!-- 结果集映射 
    		1.假设数据库字段是user_id,user_pwd,实体类属性是id,pwd
		 	2.假设要返回的对象是User,可以利用resultmap进行整合
	-->
    <resultMap id="UserMap" type="User">
    	<!--对于其他相同的属性可以不用配置-->
        <result column="user_id" property="id"/>
        <result column="user_pwd" property="pwd"/>
    </resultMap>
    <select id="getbyId" resultMap="UserMap" parameterType="int">
        select * from mybatis.user where id = #{id};
    </select>

2.多对一、一对多

pojo:

public class Student {
    private int id;	//primary key
    private String name; 
    private Teacher teacher; //对应的老师
    private int tid; //对应的老师id
}

public class Teacher {
    private int id; //primary key
    private String name; 
    List<Student> students; //对应的学生
}
  1. 多个学生对应一个老师
    <mapper namespace="DAO.StudentMapper">
    
        <!--联表查询  推荐-->
        <!--1.查询出所有参数-->
        <select id="getStudent2" resultMap="Student_Teacher2">
            select s.id as s_id,
            s.name as s_name,
            s.tid as t_id,
            t.name as t_name
            <!--起别名-->
            from mybatis.student as s
            left join mybatis.teacher as t
            on s.tid = t.id
        </select>
        <!--2.结果集映射-->
        <resultMap id="Student_Teacher2" type="pojo.Student">
            <result property="id" column="s_id"/>
            <result property="name" column="s_name"/>
            <result property="tid" column="t_id"/>
            <!--                成员变量           成员变量类型-->
            <association property="teacher" javaType="pojo.Teacher">
                <!--成员变量的成员变量设置成查询出来的参数-->
                <result property="id" column="t_id"/>
                <result property="name" column="t_name"/>
            </association>
        </resultMap>
        
        <!--子查询-->
        <!--1.查出所有学生-->
        <select id="getStudent" resultMap="Student_Teacher">
            select * from mybatis.student;
        </select>
        <!--2.在map里做对应的映射,对于teacher变量用"association"-->
        <resultMap id="Student_Teacher" type="pojo.Student">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="tid" column="tid"/>
            <!--              成员变量       查询出来的参数      成员变量类型         嵌套查询,参数为查询出来的参数-->
            <association property="teacher" column="tid" javaType="pojo.Teacher" select="getTeacher"/>
        </resultMap>
        <!--3.嵌套查询-->
        <select id="getTeacher" resultType="pojo.Teacher">
            select * from mybatis.teacher where id = #{id}
        </select>
    
    </mapper>
    
  2. 一个老师对应多个学生
    <mapper namespace="DAO.TeacherMapper">
    
        <!--联表查询-->
        <select id="getTeacher2" resultMap="Teacher_Student2">
            select t.id   as t_id,
                   t.name as t_name,
                   s.id   as s_id,
                   s.name as s_name,
                   s.tid  as s_tid
            from mybatis.teacher as t
                     left join mybatis.student s
                               on t.id = s.tid
        </select>
        <resultMap id="Teacher_Student2" type="pojo.Teacher">
            <result property="id" column="t_id"/>
            <result property="name" column="t_name"/>
            <!--          成员变量              成员变量类型        列表包含类型-->
            <collection property="students" javaType="List" ofType="pojo.Student">
                <result property="id" column="s_id"/>
                <result property="name" column="s_name"/>
                <result property="tid" column="s_tid"/>
            </collection>
        </resultMap>
    
        <!-- 子查询 -->
        <select id="getTeacher" resultMap="Teacher_Student">
            select *
            from mybatis.teacher
        </select>
        <resultMap id="Teacher_Student" type="pojo.Teacher">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <collection property="students" column="id" javaType="List" ofType="student" select="getStudent"/>
        </resultMap>
        <select id="getStudent" resultType="pojo.Student">
            select * from mybatis.student where tid = #{id}
        </select>
    
    </mapper>
    

3、动态SQL

动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
pojo:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

四、SQL注入

SQL注入攻击是指恶意拼接SQL作为参数,传递给Web服务器,进而传给数据库服务器以执行数据库命令,获取数据库的信息以及提权。
举例:

SELECT * FROM user WHERE name = '" + name + "' AND psw = '"  + psw + "';
String name = "' or '1=1"
String psw = "' or '1=1"

拼接成

SELECT * FROM user WHERE `name` = '' or '1=1' AND `psw` = '' or '1=1'

此SQL语句相当于SELECT * FROM user,即不需要name和psw,通过SQL注入查出了所有用户

在MyBatis编写SQL语句的参数的2种方式:

  • ${value}:表示拼接字符串。会引起SQL注入问题。
  • #{value}:在预处理时,用占位符?来替代参数部分。可以解决SQL注入问题。

也就是这样即可解决SQL注入的问题

select * from mybatis.user where name like concat('%',#{str},'%');

五、缓存

1.简介

  1. 用户在查询数据时不用从磁盘上查询,而是从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题;
  2. 减少和数据库的交互次数,减少系统开销,提高系统效率。
  3. 经常查询且不经常改变的数据,可使用缓存;

2.一级缓存

  1. 仅对一个会话中的数据进行缓存,即缓存只在一个SqlSession从获取到关闭这个区间有效。
  2. select 语句的结果将会被缓存。
  3. insert、update 和 delete 语句会刷新缓存,此时再查询之前查过的结果也需要重新执行SQL。

3.二级缓存

  1. 基于namespace级别的缓存,即一个Mapper中有效;
  2. 需要在Mapper.xml中手动开启:,就可以达成以下效果:
    - select语句的结果将会被缓存;
    - insert、update和delete语句会刷新缓存;
    - 使用LRU算法(Least Recently Used)来清除不需要的缓存;
    - 缓存不会定时进行刷新(即没有刷新间隔)。
    - 缓存会保存1024 个列表或对象的引用 。
    - 缓存会被视为读/写缓存,即获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
  3. 工作机制:
    - 一个会话中查询的数据,会放在一级缓存中;
    - 会话关闭,一级缓存失效,其中的数据被保存到二级缓存中;
    - 开启新的会话,先读取二级缓存,再读取当前会话的一级缓存;
    - 不同Mapper的数据存放在各自的缓存中。

总结

因为基础不牢固,我学这些也只是学了点皮毛,争取学完SQL和JDBC之后再来补全相应的知识点

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值