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>