一,概述:
Mybatis介绍:
Mybatis是一款优秀的持久层框架,它支持定制化SQL,存储过程以及高级映射。mybaits 避免了几乎所有的JDBC代码和手动设置参数以及获取结果集 。
Mybatis可以使用简单的xml或注解来配置和映射原生信息,将接口和java的POJO(Plain Old java Objects,普通java对象)映射成数据库中的记录。
Mybatis是基于JDBC做的简单的映射包装。
Mybatis架构:
二,Mybatis使用
1, pom 文件引入依赖
<!--MySQL的驱动jar-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
2,mybatis-config.xml :全局配置文件
配置数据源,事务,加载映射文件。 后文详解
3,创建pojo类(提供基本的get/set方法)
/**
* 创建Pojo类,和数据库表Student对应
* 属性需要与数据库一一对应
*/
public class Student {
private int SID;
private String Sname;
private String Ssex;
private int Sage;
省略get和set方法
}
4,创建Mapper.java接口
该接口中的方法名需要唯一,每一个接口方法均与Mapper.xml文件sql语句一一映射
public interface StudentMapper {
// 需求:通过ID查询Student表中用户信息
//select * from Student where SID = XXX
public Student getStudentById(int sid);
}
5,Mapper.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">
<!--
mapper标签:试试数据库表映射最外层标签
namespace:指定接口的全路径名(包名+类名)
-->
<mapper namespace="com.dao.StudentMapper">
<!--
select查询操作标签
id属性:对应接口中方法名,必填项、且在同一个namespace,ID不能重复
#{XXX}:占位符 里面填写的是方法中的参数名
parameterType属性:指定入参类型
resultType属性:执行返回参数类型 指定全路径名
-->
<select id="getStudentById" parameterType="java.lang.Integer" resultType="com.bean7.Student">
select * from Student where SID = #{sid}
</select>
</mapper>
将Mapper.xml 配置到全局配置文件中 mybatis-config.xml
<mappers>
<mapper resource="mapper/StudentMapper.xml"/>
</mappers>
编程使用 :一般放在启动类中
- SqlSessionFactory :会话工厂,
通过读取配置文件创建,配置文件只需读取一次即可,可以将SqlSessionFactory设置单例 - SqlSession: 会话
通过SqlSessionFactory 得到,对数据库的CRUD操作都是通过SqlSession来操作的
SqlSession是线程不安全的,将其设置为方法的局部变量
一级缓存是基于sqlsession来创建的,mybatis默认开启一级缓存
/**
* @Created with IntelliJ IDEA
* @Description:
* @Package: PACKAGE_NAME
* @author: FLy-Fly-Zhang
* @Date: 2019/7/26
* @Time: 13:56
*/
public class App {
public static void main(String[] args) throws IOException {
String resource="mybatis-config.xml";
//读取配置文件
InputStream inputStream=Resources.getResourceAsStream(resource);
//创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//设置是主动提交事务还是手动,默认手动
sqlSessionFactory.openSession(true);
//得到sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//通过动态代理产生StrudentMapper对象
StudentMapper mapper=sqlSession.getMapper(StudentMapper.class);
//调用对应接口方法,进行sql语句操作
Student student = mapper.getStudentById(1);
//若未设置主动提交事务,进行手动提交
sqlSession.commit();
System.out.println(student);
}
}
三,配置文件详解:
全局配置文件
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mybatis
db.username=root
db.password=12345678
<!--properties标签:读取配置文件,一般配置数据源-->
<properties>-->
<property name="db.properties" value="db.properties"/>
</properties>
<!--settings标签:设置mybatis全局性配置-->
<settings>
<!--打开延时加载的开关-->
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--将积极加载改为消极加载即按需加载-->
<!--<setting name="aggressiveLazyLoading" value="false"/>-->
<!--开启二级缓存-->
<!--<setting name="cacheEnabled" value="true"/>-->
</settings>
<!--typeAliases标签:取别名-->
<typeAliases>
<!--
typeAlias:指定单个的类型取别名
type属性:指定的要取别名的类的全路径名
alias属性:取别名
-->
<typeAlias type="com.bean7.Student" alias="student"/>
<!--
package标签:批量取别名
name属性:指定要取别名的包路径
-->
<!--<package name="com.bean7"/>-->
</typeAliases>
<!--环境配置-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!-- 配置数据源,采用property进行配置 -->
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</dataSource>
<!--配置数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="xxxx"/>
<property name="password" value="xxxxx"/>
<!--读取配置-->
<!--<property name="password" value="${passsword}"/>-->
</dataSource>
</environment>
</environments>
<!--对象映射-->
<mappers>
<!--
mappers映射有三种方式:
resource方式:
对单个的mapper进行映射、
mapper.xml和mapper.java文件名可以不一样,可以不用存放在同一个目录下
class方式:
对单个的mapper进行映射
mapper.xml和mapper.java文件名必须一样,必须存放在同一个目录下
package方式:
批量对mapper映射
mapper.xml和mapper.java文件名必须一样,必须存放在同一个目录下
-->
<mapper resource="mapper7/StudentMapper.xml"/>
<!--<mapper class="com.dao5.StudentMapper"/>-->
<!--<package name="com.dao7"/>-->
</mappers>
setting标签
mapper配置文件
#{} 和${}区别:
mybatis中有两个常见的符号#和KaTeX parse error: Expected 'EOF', got '#' at position 25: …的时候是很常见的,我的理解就是#̲是需要进行预编译的,是字符串进…是直接进行字符串的替换工作,两者各有有缺点。
- #{} :表示一个占位符 ?
-
通过#{ }可以实现preparedStatement向占位符中设置值,
-
自动进行java类型和jdbc类型转换,
-
#{ }可以有效防止sql注入。
-
#{ }可以接收简单类型值或pojo属性值。
-
如果parameterType传输单个简单类型值,#{ }括号中可以是value或其它名称。
我们一般在刚刚接触到mybatis的时候都是使用的是#{变量名字},来进行sql语句的赋值工作,比如 select * from table_name where name = #{name},来进行查询,在接口里面传入Map或者是String都是可以的,这样的是mybatis进行了语句的编译工作,#{name},必须要放到name=后面,这样才会编译通过,进行执行sql语句。
- $ {}
-
${ }可以将parameterType 传入的内容拼接在sql中
-
不进行jdbc类型转换,
-
$ { }可以接收简单类型值或pojo属性值,
-
如果parameterType传输单个简单类型值,${ }括号中只能是value。
我们需要进行变化传输sql语句,这个时候一般都会用到的是等mybatis里面的动态标签来动态拼接sql语句,但是有的时候根据一些业务场景是需要传输表名或者是特定的变量名的,这个时候就需要根据业务来动态的改变查询的表名等问题,这个时候 我的感觉就是单纯的字符串替换,比如,select * from table_name where name = ${name}这个时候mybatis不需要编译而是直接进行字符串的替换工作,比如我要传入一个表名,select * from KaTeX parse error: Expected 'EOF', got '#' at position 26: …} where name = #̲{name},这个时候在前台就…{tableName}就是单纯的字符串替换,而#{name}则需要进行编译才可以赋值
- 注意:
一般还是使用#,因为#是比较安全的一种传输方式,在一些渗透和安全性校验的时候,$ 不是特别安全,容易引起sql的注入问题,导致毁灭性灾难,但是也不是说一点不能用,只能说不可以从前台传输有关于sql的语句来使用 $ 否则就会出现删除数据的问题。
<!--
mapper标签:试试数据库表映射最外层标签
namespace:指定接口的全路径名(包名+类名)
-->
<mapper namespace="com.dao7.StudentMapper">
<!--
resultMap标签:指定返回类型
id属性:取名字
type属性:指定映射的JAVA对象,对应类的全路径
-->
<resultMap id="resultStudent" type="com.bean7.Student">
<!--
id标签:指定主键的映射关系
result标签:非主键的映射关系
column属性:指定数据库字段名
jdbcType属性:指定数据库字段的类型
property属性:指定java类的属性名
javaType属性:指定JAVA属性的类型
typeHandler属性:执行类型映射操作
-->
<id column="SID" property="SID" javaType="java.lang.Integer" jdbcType="INTEGER"></id>
<result column="Sname" property="name"></result>
<result column="Ssex" property="Ssex"></result>
<result column="Sage" property="Sage"></result>
</resultMap>
<!--
select查询操作标签
id属性:对应接口中方法名,必填项、且在同一个namespace,ID不能重复
#{XXX}:占位符 里面填写的是方法中的参数名
parameterType属性:指定入参类型
resultType属性:执行返回参数类型 指定全路径名
resultMap属性:执行返回参数类型
resultType和resultMap区别:
使用resultType是需要数据库字段和java类属性名保持一致,如果不一致则该属性无法完成映射
使用resultMap进行显性映射,可以解决数据库字段和JAVA类属性名不一致的问题
-->
<select id="getStudentById" parameterType="java.lang.Integer" resultMap="resultStudent">
select * from Student where SID = #{sid}
</select>
<!--插入操作-->
<insert id ="addStudent" parameterType="com.bean7.Student">
insert into Student (SID,Sname) values (#{SID},#{Sname})
</insert>
<!--删除操作-->
<delete id=""/>
<!--修改操作-->
<update id=""/>
mybatis接口绑定形式:配置和注解
配置:
- mapper.xml和mapper.java 绑定
- mapper.xml文件中的namespace属性和mapper.java接口的类全路径保持一致
- mapper.xml文件sql的CRUD的id属性和mapper.java接口中对应的方法名保持一致,且一个xml文件中,id不能重复
- mapper.xml文件中的操作的parameterType属性和mapper.java接口中对应的方法入参类型保持一致。
- mapper.xml文件中的操作的resultType属性和mapper.java接口中对应方法返回类型保持一致。
注解形式:
- 当方法参数只有一个时,不需要使用@param注解
- 当方法参数有多个时,需要使用@param注解将形参和@param参数进行一一绑定。
public interface StudentMapper {
/**
* 通过对象新增
* @param student
* @return
*/
@Insert("insert into student(student_number, student_name, age) values (#{studentNumber, jdbcType=VARCHAR}, #{studentName, jdbcType=VARCHAR}, #{age, jdbcType=INTEGER})")
int insertByObject(Student student);
/**
* 通过map新增
* @param map
* @return
*/
@Insert("insert into student(student_number, student_name, age) values (#{studentNumber, jdbcType=VARCHAR}, #{studentName, jdbcType=VARCHAR}, #{age, jdbcType=INTEGER})")
int insertByMap(Map<String, Object> map);
/**
* 通过编号查询
* @param studentNumber
* @return
*/
@Select("select * from student where student_number = #{studentNumber}")
@Results({
@Result(column = "student_number", property = "studentNumber"),
@Result(column = "student_name", property = "studentName"),
@Result(column = "age", property = "age")
})
Student findByStudentNumber(String studentNumber);
/**
* 通过姓名查询
* @param studentName
* @return
*/
@Select("select * from student where student_name = #{studentName}")
@Results({
@Result(column = "student_number", property = "studentNumber"),
@Result(column = "student_name", property = "studentName"),
@Result(column = "age", property = "age")
})
List<Student> findByStudentName(String studentName);
/**
* 通过编码删除
* @param studentNumber
* @return
*/
@Delete("delete from student where student_number = #{studentNumber}")
int deleteByStudentNumber(String studentNumber);
/**
* 通过对象修改
* @param student
* @return
*/
@Update("update student set student_name = #{studentName}, age = #{age} where student_number = #{studentNumber}")
int updateByObject(Student student);
/**
* 通过编码修改名字
* 传多个参数时必须使用@Param("")
* @param studentName
* @param StudentNumber
* @return
*/
@Update("update student set student_name = #{studentName} where student_number = #{studentNumber}")
int updateStudentNameByStudentNumber(@Param("studentName") String studentName, @Param("studentNumber") String StudentNumber);
}