引入依赖、实体类、建表、Mybatis主配置文件都和上篇示例一致,所需变化的只有DAO接口和映射配置文件。
保存用户
- 持久层接口中增加
/**
* 保存用户
* @param user
* @return 影响数据库记录的行数
*/
int saveUser(User user);
- 映射配置文件中增加
<!-- 保存用户-->
<insert id="saveUser" parameterType="com.mg.entity.User">
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
细节:
-
parameterType 属性: 代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。
-
sql 语句中使用#{}字符: 它代表占位符, 相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。
-
#{}中内容的写法: 由于我们保存方法的参数是 一个 User 对象,此处要写 User 对象中的属性名称。它用的是 ognl 表达式。
-
ognl 表达式: 它是 apache 提供的一种表达式语言, 全称是:Object Graphic Navigation Language 对象图导航语言。它是通过对象的取值方法来获取数据,在写法上把get省略。如:类中写法:user.getUserName() OGNL的写法为:user.userName
#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user. 而直接写 username。
保存用户时获取插入数据的ID
<insert id="saveUser" parameterType="com.mg.entity.User">
<!-- 配置保存时获取插入的 id -->
<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
细节:
- keyColumn:表的列名
- keyProperty:实体类的属性名
- order:什么时候执行。AFTER:插入语句执行之后执行 BEFORE:插入语句执行之前执行
更新用户
- 持久层接口中增加
/**
* 更新用户
* @param user
* @return 影响数据库记录的行数
*/
int updateUser(User user);
- 映射配置文件
<!-- 更新用户 -->
<update id="updateUser" parameterType="com.mg.entity.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},
address=#{address} where id=#{id}
</update>
删除用户
- 持久层接口中增加
/**
* 根据 id 删除用户
* @param userId
* @return
*/
int deleteUser(Integer userId);
- 映射配置文件
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{uid}
</delete>
细节:
- parameterType取值也可以写 int Integer等,因为Mybatis作了别名
- 当参数是基本类型及其包装类或者String并且只有一个参数时,SQL语句中#{}中的形参名称可以随便写。这里可以是userId,uid或者其他任何符合命名规范的写法
根据ID查询一个元素
-
持久层接口中增加
/** * 根据 id 查询 * @param userId * @return */ User findById(Integer userId);
-
映射配置文件
<!-- 根据 id 查询 --> <select id="findById" resultType="com.mg.entity.User" parameterType="int"> select * from user where id = #{uid} </select>
细节:
- resultType 属性:用于指定结果集的类型。
模糊查询
-
持久层接口
/** * 根据名称模糊查询 * @param username * @return */ List<User> findByName(String username);
-
映射配置文件
<!-- 根据名称模糊查询 --> <select id="findByName" resultType="com.mg.entity.User" parameterType="String"> select * from user where username like #{username} </select>
细节:
-
对于返回类型是List等集合类型时,resultType的取值为List集合中元素的类型
-
我们在配置文件中没有加入%来作为模糊查询的条件,所以在测试传入字符串实参时,就需要给定模糊查询的标识% 如: List
users = userDao.findByName("%王%"); -
此时控制台打印出来的SQL语句为:
select * from user where username like ?
配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“?”
模糊查询的另一种配置方式 ${}
<!-- 根据名称模糊查询 -->
<select id="findByName" parameterType="string" resultType="com.mg.entity.User">
select * from user where username like '%${value}%'
</select>
细节:
-
${value}的写法就是固定的,不能写成其它名字 。因为源码中写死了
-
程序代码中就不需要加入模糊查询的匹配符%了
List
users = userDao.findByName("王"); -
控制台语句为:
select * from user where username like ’%王%‘
#{}与${}的区别
-
-
#{}表示一个占位符号
- 通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换
- #{}可以有效防止 sql 注入。
- #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值, #{}括号中可以是 value 或其它名称。
- #{}会自动加上单引号
-
-
- ${}表示拼接 sql 串
- 通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换,
- ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值, ${}括号中只能是 value。
- ${}不会自动加上单引号
使用聚合函数查询
-
持久层接口
/** * 查询总记录条数 * @return */ int findTotal();
-
映射配置文件
<!-- 查询总记录条数 --> <select id="findTotal" resultType="int"> select count(*) from user; </select>
注意:
以上的CRUD方法,增、删、改方法在测试时需要注意提交事务 sqlSession.commit() 查询方法则不需要
Mybatis 与 JDBC 编程的比较
- 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。 解决:在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。
- Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大, sql 变动需要改变 java 代码。 解决:将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
- 向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数对应。 解决:Mybatis 自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的类型。
- 对结果集解析麻烦, sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对 象解析比较方便。 解决:Mybatis 自动将 sql 执行结果映射至 java 对象,通过 statement 中的 resultType 定义输出结果的 类型