1. MyBatis是什么?
之前使用的是JDBC,其中大量的代码是重复的冗余的。只有SQL是程序员需要控制的。 MyBatis是一个半自动化的ORM框架。半自动化是相对于Hibernate而言的。 Hibernate是完全的ORM框架,但是学习成本较高,因为封装的程度太高,导致性能不佳。 因此,MyBatis是目前较好的一个选择。 什么是ORM?指的是对象和关系之间的映射。
2. MyBatis的开发步骤
1.新建数据库、三个表 (mybatis-example)
2.建POJO
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer empId ;
private String empName ;
private Double empSalary ;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private Integer pid ;
private String pname , address ;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Tiger {
private String tid ;
private String tname ;
private Integer age ;
}
3.添加依赖 (mysql , mybatis , junit , lombok)
xml
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
4.新建EmpMapper 、PersonMapper 、TigerMapper接口
java
public interface EmpMapper {
List<Emp> getEmpList();
List<Emp> getEmpList2();
List<Emp> getEmpList3();
}
public interface PersonMapper {
List<Person> getPersonList();
Person getPerson(Integer pid);
Person getPersonByPname(String pname);
List<Person> getPersonList2(String tableName);
}
public interface TigerMapper {
Tiger getTiger(Integer tid);
void addTiger(Tiger tiger);
List<Tiger> getTigerByCondition(Integer tid , String tname , Integer age);
List<Tiger> getTigerByCondition2(@Param("tid") Integer tid ,@Param("tname") String tname ,@Param("age") Integer age);
List<Tiger> getTigerByCondition3(Map paramMap);
int getTigerCount(String tname);
Map<String,Object> getTigerInfoByTid(Integer tid);
void addTiger2(Tiger tiger);
}
5.在resources 目录下新建com.bottom.mybatis.mapper 目录,并新建三个mapper.xml文件
EmpMapper.xml
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="com.bottom.mybatis.mapper.EmpMapper">
<select id="getEmpList" resultType="Emp">
select * from t_emp
</select>
<select id="getEmpList2" resultType="Emp">
select emp_id as empId ,
emp_name as empName ,
emp_salary from t_emp
</select>
<select id="getEmpList3" resultMap="EmpResultMap">
select a ,
b ,
c from t_emp
</select>
<!-- 定义EmpResultMap这种映射关系 -->
<resultMap id="EmpResultMap" type="Emp">
<id property="empId" column="a"/>
<result property="empName" column="b"/>
<result property="empSalary" column="c"/>
</resultMap>
</mapper>
PersonMapper.xml
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的值本质上就是字符串,取值可以任意。但是我们强烈建立取值是Mapper的全类名 -->
<mapper namespace="com.bottom.mybatis.mapper.PersonMapper">
<!-- id的取值本质上是字符串,可以随便写,只要保证namespace+id是唯一的即可。但是强烈建议是方法名 -->
<select id="getPersonList" resultType="Person">
select * from t_person
</select>
<select id="getPerson" resultType="Person">
select * from t_person where pid = #{pid}
</select>
<select id="getPersonByPname" resultType="Person">
select * from t_person where pname = ${pname}
</select>
<select id="getPersonList2" resultType="Person">
select * from ${tableName}
</select>
</mapper>
TigerMapper.xml
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的值本质上就是字符串,取值可以任意。但是我们强烈建立取值是Mapper的全类名 -->
<mapper namespace="com.bottom.mybatis.mapper.TigerMapper">
<!-- 当输入参数是单个的基本类型时,#{}中随便写 , 一般取值是tid(和Mapper方法中的形参名称一致)或者是'value' -->
<select id="getTiger" resultType="Tiger">
select * from t_tiger where tid = #{value}
</select>
<!--
parameterType="Tiger"可以省略
select表示查询,此时resultType必须要写。相反的,insert,update,delete都不需要写
-->
<!-- useGeneratedKeys=true 表示执行insert操作之后,返回自增长的值 -->
<!-- keyProperty 表示 得到的自增长的值将设置给哪一个属性 -->
<insert id="addTiger" parameterType="Tiger" useGeneratedKeys="true" keyProperty="tid">
insert into t_tiger values(0,#{tname},#{age})
</insert>
<select id="getTigerByCondition" resultType="Tiger">
select * from t_tiger
where tid = #{param1} or tname like #{arg1} or age = #{arg2}
</select>
<select id="getTigerByCondition2" resultType="Tiger">
select * from t_tiger
where tid = #{tid} or tname like #{tname} or age = #{age}
</select>
<select id="getTigerByCondition3" resultType="Tiger">
select * from t_tiger
where tid = #{tid} or tname like #{tname} or age = #{age}
</select>
<select id="getTigerCount" resultType="int">
select count(*) from t_tiger
where tname like concat('%',#{value},'%')
</select>
<select id="getTigerInfoByTid" parameterType="int" resultType="map">
select * from t_tiger where tid = #{value}
</select>
<insert id="addTiger2" parameterType="Tiger">
<!-- keyProperty="tid" 查询结果集中的数据赋值给Tiger中的"tid"属性 -->
<!-- keyColumn="abcd" 查询结果集中的列名为"abcd"这一列的值取出来作为key -->
<selectKey keyProperty="tid" keyColumn="abcd" resultType="string" order="BEFORE">
select UUID() as abcd , 1 , 'hello' , 'java'
</selectKey>
insert into t_tiger values(#{tid},#{tname},#{age})
</insert>
</mapper>
6.新增mybatis的配置文件: (mybatis-config.xml)
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="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<package name="com.bottom.mybatis.pojo"/>
</typeAliases>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis-example"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 注册mapper映射文件 -->
<mappers>
<!--
<mapper resource="mapper/PersonMapper.xml"/>
<mapper resource="mapper/TigerMapper.xml"/>
<mapper resource="mapper/EmpMapper.xml"/>
-->
<!-- 当使用package标签时,name属性的值必须是Mapper接口的包名 -->
<package name="com.bottom.mybatis.mapper"/>
</mappers>
</configuration>
7.新建单元测试类
java
public class EmpTest {
private SqlSession sqlSession ;
private EmpMapper empMapper ;
@BeforeEach
public void setup() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
empMapper = sqlSession.getMapper(EmpMapper.class);
}
@AfterEach
public void teardown() throws SQLException {
if(sqlSession!=null && !sqlSession.getConnection().isClosed()){
sqlSession.commit();
sqlSession.close();
}
}
//1.演示结果集的列名和要映射的对象中的属性名称不一致的情况
@Test
public void test01(){
empMapper.getEmpList().forEach(System.out::println);
}
//2.通过使用别名的方式解决列名和属性名不一致的情况
@Test
public void test02(){
empMapper.getEmpList2().forEach(System.out::println);
}
//3.通过使用ResultMap的方式解决列名和属性名不一致的情况
@Test
public void test03(){
empMapper.getEmpList3().forEach(System.out::println);
}
}
3. MyBatis中的传参符号
-
#{} 相当于 占位符 ?
-
${} 拼凑字符串,可能会导致注入式漏洞
4. MyBatis中的输入参数
1) 单个基本类型 - 名称任意
#{value} , #{pid} , #{abcdefg}
2) 实体类型 - 名称是实体类的属性名
#{tid} , #{tname} , #{age}
3) 零散的输入类型
- arg0 , arg1 , arg2 ...
- param1 , param2 ....
- @Param("tid")
4) Map输入类型
5. MyBatis中的输出参数
- 输出单个的简单类型 resultType="int"
- 输出实体类型 resultType="Tiger"
- 输出List类型 resultType="Tiger"
- 输出Map类型 resultType="map"
6. 查询结果集的列名和属性名不一致的三种解决方法 (用自己定义的resultmap去解决)
7. 在mybatis-config.xml文件中注册Mapper.xml文件的两种方式
- mapper resource 每一个xml都注册进去
xml
<!-- 注册mapper映射文件 -->
<mappers>
<mapper resource="mapper/PersonMapper.xml"/>
<mapper resource="mapper/PersonMapper.xml"/>
<mapper resource="mapper/TigerMapper.xml"/>
</mappers>
- package 直接注册包路径
xml
<mappers>
<package name="com.bottom.mybatis.mapper"/>
</mappers>