Mybatis复习
# Mybatis简介
# 概述
- Mybatis作用
- Mybatis是支持定制化SQL、存储过程以及高级映射的持久层半自动化框架
- Mybatis避免了几乎所有的JDBC代码、手动设置参数以及获取结果集。
- Mybatis使用简单的XML用于配置和原始映射,将接口和Java的POJO类映射成数据库中的记录。
- 开发者只需要关注SQL本身,而无需花费精力处理注册驱动、创建connection、statement、设置参数等JDBC中繁杂的过程。
- 为什么要使用Mybatis
- JDBC:SQL加载在Java代码中,耦合度高,硬编码不易维护,需要自行创建Connection等对象,流程繁琐。
- Hibernate:复杂的SQL处理不便、自动生成的SQL不容易做优化,全映射无法只映射部分字段导致数据库性能下降。
- Mybatis:是半自动化的,开发者可以优化SQL。
- Mybatis使用流程
- 在项目中引入Mybatis核心包和依赖包,编辑核心XML配置文件,添加数据库连接信息
- 创建与数据库中表对应的Java POJO
- 创建Mapper配置文件,并在核心配置文件中注册这些Mapper
- 创建Mybatis提供的SqlSessionFactory工厂,执行SQL语句,关闭SqlSession
# Mybatis核心API
- SqlSessionFactoryBuilder:用于读取核心配置文件,创建SqlSessionFactory,创建完毕后就不需要了。
- SQLSessionFactory:创建SqlSession的工厂,是一个接口,定义了openSession的不同重载方法。
- SqlSession:是连接到数据库的一个会话,定义了数据库的操作方法如SelectOne()、SelectList()等,是线程不安全的。
# MyBatis CRUD
想要查看执行的详情,可以在配置中settings标签内加入下面的setting:<setting name="logImpl" value="STDOUT_LOGGING"/>
。
# 查询
下面是一个mapper例子:
<mapper namespace="com.company.CustomerMapper">
<!--根据ID查询用户-->
<select id="queryCustomerById" parameterType="Int" resultType="com.company.pojo.Customer">
SELECT * FROM `mydb`.`customer` WHERE cust_id = #{cust_id}
</select>
<!--根据用户名模糊查询用户-->
<select id="queryCustomerByName" parameterType="String" resultType="com.company.pojo.Customer">
SELECT * FROM `mydb`.`customer` WHERE cust_name LIKE '%${value}%'
</select>
</mapper>
2
3
4
5
6
7
8
9
10
11
在执行查询时,#{}
中的内容会被占位符?
替代,传入参数时会自动加上引号''
,并且可以防止SQL注入。
${}
表示拼接字符串,传入的内容不会做类型转换,但不能防止SQL注入。在进行模糊查询时,除了像例子中那样使用'%${value}%'
的方式,还可以使用#{value}
并将传入的String直接改为%value%
以规避SQL注入的风险。
# 插入
<mapper namespace="com.company.CustomerMapper">
<insert id="addCustomer" parameterType="com.company.pojo.Customer">
<!--在插入后获取最后一个id存回对象中-->
<selectKey keyColumn="cust_id" keyProperty="cust_id" reultType="Integer" order="AFTER">
SELECT last_insert_id()
</selectKey>
INSERT INTO `mydb`.`customer`(cust_name, cust_profession, cust_phone) VALUES(#{cust_name}, #{cust_profession}, #{cust_phone})
</insert>
</mapper>
2
3
4
5
6
7
8
9
10
在对数据库的内容进行改动时需要自己提交事务:
public void insertTest() {
SqlSession sqlSession = MyBatisUtils.openSession();
Customer customer = new Customer("Judy", "Teacher", "13912341234");
sqlSession.insert("addCustomer", customer);
sqlSession.commit(); //手动提交
sqlSession.close();
//此时customer对象中已经被写入了获取到的id
}
2
3
4
5
6
7
8
# 更新与删除
<mapper namespace="com.company.CustomerMapper">
<update id="updateCustomer" parameterType="com.company.pojo.Customer">
UPDATE `mydb`.`customer` SET cust_name=#{cust_name} WHERE cust_id=#{cust_id}
</update>
<delete id="deleteCustomer" parameterType="com.company.pojo.Customer">
DELETE FROM `mydb`.`customer` WHERE cust_id=#{cust_id}
</delete>
</mapper>
2
3
4
5
6
7
8
9
# MyBatis Mapper开发
尽管我们可以使用传统模式,定义DAO接口,再编写对应的实现类来调用MyBatis,但是MyBatis提供了动态代理的功能,使得我们只需要定义接口而无需自己编写实现类。不过需要遵从以下要求:
- namespace必须要和Mapper接口类路径一致。
- id必须和接口方法一致。
- parameterType必须和接口方法参数类型一致。
- resultType必须和接口方法返回值一致。
public void testMappepr() {
SqlSession sqlSession = MyBatisUtils.openSession();
CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
Customer customer = mapper.queryCustomerById(8);
}
2
3
4
5
在编写mapper时,如果传入的参数是单个,可以接受基本类型、对象类型(包括集合类型)的值,无需任何处理;而如果是任意多个参数,那么MyBatis会重新包装成map再传入,map的key是#{param1},#{param2},...
或者#{arg0},#{arg1},...
。
- 如果想要自定义key的话可以在调用接口方法时在对应的参数前加上
@Param("myKey")
的注解。 - 也可以自己创建一个Map,把参数的key和value放进去,那么mapper中就使用自定义的key名称获取value。
- 还可以传入pojo类,此时使用的key名称就要和pojo类对应的的属性名相同。
在定义Mapper时,可以自定义resultMap,即指定把数据库中的哪一列封装成对象的哪个属性:
<reslutMap id="userMap" type="com.company.pojo.User">
<!--id指定主键-->
<id column="db_col_name" property="pojo_property_name"/>
<reslut column="db_col_name" property="pojo_property_name"/>
<!--级联对象设置方法1-->
<reslut column="db_col_name2" property="pojo_innerobj.propername"/>
<!--级联对象设置方法2,一般使用这种方法-->
<association property="pojo.innerobj" javaType="objClassType">
<reslut column="db_col_name2" property="propername"/>
</association>
</resultMap>
2
3
4
5
6
7
8
9
10
11
在涉及级联属性时,就必须使用resultMap来指定查询结果和属性的映射关系。association标签也常使用select属性进行用于分步查询(支持懒加载)。
涉及一对多的关系时,可以在resultMap中使用<collection>
标签:
<collection property=" orders" ofType="Order">
<id column="order_id" property=" order_id"/>
<id column="order_name" property="order_name">
<id column=" order_num" property="order_num">
</collection>
2
3
4
5
6
# MyBatis核心配置文件
在核心xml配置文件中,在<configuration>
标签内,可以添加很多类型的配置信息,如果要添加则要按下面的顺序使用:
<properties>
标签:定义很多<property name="aaa" value="long text">
,使用键值对的方式添加属性。在下文中就可以通过"${aaa}"
这样的形式代替填写值。实际开发中,往往会把单独要设置的属性存放到单独的.properties文件中,再在properties标签后加上resource="xxx.properties"就可以直接使用。<settings>
标签:会改变MyBatis运行时的行为,例如将下划线命名和驼峰命名进行转换等。详见:www.mybatis.org/mybatis-3/zh/configuration.html#settings<typeAliases>
标签:定义多个类型别名,可以使用<typaAlias alias="User" type="com.company.pojo.User">
对单个类进行定义,也可以使用<package name="package name">
为包下面的所有类设置别名(直接为类名),如果有子包的类名产生同名冲突可以使用@Alias("name")
注解解决。<typeHandlers>
标签:定义类型处理器,用于转换数据库类型到Java类型,只在需要使用自定义类型的时候需要。<plugins>
标签:添加插件。<environments>
标签:可以定义多个不同的数据库环境,例如DEV开发环境和SIT测试环境等等,根据需要可以切换环境。实际开发中往往使用Spring来进行管理数据源和配置。<databaseIDProvider>
标签:指定使用的数据库类型,MyBatis可以根据不同的类型发送不同的SQL语句。定义后,可以在Mapper中通过databaseId="mysql"
来声明仅在连接的数据库为Mysql时才执行该语句。<mappers>
标签: 用于加载映射文件,但映射文件的名称必须要和对应接口一致,并且要和接口存放于同一目录。可以用<mapper>
标签指定单个要加载的映射文件,也可以使用<package name="pkg name">
指定某个包下的所有映射文件。