Mybatis入门笔记
Mybatis入门笔记#
前言
我还没学SQL和JDBC怎么办,被迫来学Mybatis......当然了如果各位看官有什么莫名其妙的报错的话,可以私信我,我如果会的话会尽量回复的(/doge)
一、简介
1.什么是Mybatis#
- MyBatis 是一款优秀的持久层框架
- 它支持自定义 SQL、存储过程以及高级映射。
- MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
- 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(映射器)
- properties:我们可以通过properties属性来实现引用配置文件(方便后期修改)
- settings:调整设置
- typeAliases:降低冗余的全限定类名书写
- environments:可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境
- mappers:每一个Mapper.xml都需要在MyBatis核心配置文件中注册
2.第一个Mybatis#
-
创建一个普通的maven项目
-
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>
-
在resources目录下创建db.properties,写入连接数据库内容
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306?useSSL=false&useUnicode=true&characterEncoding=UTF-8 username=root password=*****
-
在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>
-
创建工具类 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); } }
-
创建Dao接口类 UserMapper.java
public interface UserMapper { public List<User> getUserList(); }
-
创建接口实现类 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>
-
创建测试类
@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(); }
三、语法
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; //对应的学生
}
- 多个学生对应一个老师
<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>
- 一个老师对应多个学生
<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.简介#
- 用户在查询数据时不用从磁盘上查询,而是从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题;
- 减少和数据库的交互次数,减少系统开销,提高系统效率。
- 经常查询且不经常改变的数据,可使用缓存;
2.一级缓存#
- 仅对一个会话中的数据进行缓存,即缓存只在一个SqlSession从获取到关闭这个区间有效。
- select 语句的结果将会被缓存。
- insert、update 和 delete 语句会刷新缓存,此时再查询之前查过的结果也需要重新执行SQL。
3.二级缓存#
- 基于namespace级别的缓存,即一个Mapper中有效;
- 需要在Mapper.xml中手动开启:,就可以达成以下效果:
- select语句的结果将会被缓存;
- insert、update和delete语句会刷新缓存;
- 使用LRU算法(Least Recently Used)来清除不需要的缓存;
- 缓存不会定时进行刷新(即没有刷新间隔)。
- 缓存会保存1024 个列表或对象的引用 。
- 缓存会被视为读/写缓存,即获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。 - 工作机制:
- 一个会话中查询的数据,会放在一级缓存中;
- 会话关闭,一级缓存失效,其中的数据被保存到二级缓存中;
- 开启新的会话,先读取二级缓存,再读取当前会话的一级缓存;
- 不同Mapper的数据存放在各自的缓存中。
总结
因为基础不牢固,我学这些也只是学了点皮毛,争取学完SQL和JDBC之后再来补全相应的知识点
作者:23DAY
出处:https://www.cnblogs.com/23DAY/p/16994506.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现