JavaEE——MyBatis持久层框架(2)
目录
-
-
- 5.6. 任务 3:添加用户
- 5.7. 任务 4:UUID 主键策略
- 5.8. 任务 5:更新用户
- 5.9. 任务 6:删除用户
- 5.10. MyBatis 解决了 JDBC 编程的问题
-
5.6. 任务 3:添加用户
第一步:创建 Mapped Statement ID
在映射文件 userinfo.xml 中添加 Mapped Statement ID,代码如下:
<insert id="insertUserInfo" parameterType="cn.itlaobing.mybatis.model.UserInfoModel"> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO userinfo(userName,userPass,birthday,gender,address) VALUES(#{userName},#{userPass},#{birthday},#{gender},#{address}); </insert>
第二步:编写单元测试
在 TestEshop 单元测试类中添加单元测试方法,代码如下:
@Test public void testInsertUser() { // 通过工厂得到 SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 插入用户对象 UserInfoModel model = new UserInfoModel(); model.setUserName("宋江"); model.setUserPass("songjiang"); model.setBirthday(new Date()); model.setGender("男"); model.setAddress("山东郓城"); sqlSession.insert("eshop.insertUserInfo", model); // 提交事务 sqlSession.commit(); // 获取用户信息主键 System.out.println(model.getId()); // 关闭会话 sqlSession.close(); }
第三步:单元测试
运行单元测试,控制台输出日志如下
15:22:11,068 DEBUG insertUserInfo:159 - ==> Preparing: INSERT INTO userinfo(userName,userPass,birthday,gender,address) VALUES(?,?,?,?,?); 15:22:11,100 DEBUG insertUserInfo:159 - ==> Parameters: 宋江(String), songjiang(String), 2017-09-22 15:22:10.833(Timestamp), 男(String), 山东郓城(String) 15:22:11,100 DEBUG insertUserInfo:159 - Preparing: SELECT LAST_INSERT_ID() 15:22:11,100 DEBUG insertUserInfo!selectKey:159 - ==> Parameters: 15:22:11,115 DEBUG insertUserInfo!selectKey:159 - <== Total: 1 15:22:11,115 DEBUG JdbcTransaction:70 - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4493d195] 新增记录的主键值是:5
- 日志中输出了执行的 sql 语句为 INSERT INTO userinfo(userName,userPass,birthday, gender,address) VALUES(?,?,?,?,?);
- 传入参数是 Parameters:宋江(String), songjiang(String), 2017-09-22
15:22:10.833(Timestamp), 男(String), 山东郓城(String) - 输出结果是:Updates: 1
5.7. 任务 4:UUID 主键策略
使用自增长作为主键生成策略存在缺陷,记录的主键值容易被猜测,从而导致不安全,例如当要删除 id=1 的记录时,如果用户输入 2,导致 id=2,则将第二条记录被删掉。 UUID 是用于生成 36 位长度的用于不重复的字符串,将此字符串作为记录的主键可以避免自增长主键的缺陷。java.util.UUID 类的 randomUUID()方法和MySQL 中的 uuid()函数都可以生成 UUID 字符串。
<insert id="uuid" parameterType="cn.itlaobing.mybatis.model.UserInfoModel"> <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String"> SELECT uuid() </selectKey> INSERT INTO userinfo(id,userName,userPass,birthday,gender,address)VALUES(#{id},#{userName},#{userPass},#{birthday},#{gender},#{address}); </insert>
5.8. 任务 5:更新用户
第一步:创建 Mapped Statement ID
在映射文件 userinfo.xml 中添加 Mapped Statement ID,代码如下:
<update id="updateUserInfo" parameterType="cn.itlaobing.mybatis.model.UserInfoModel"> update userinfo set userName=#{userName},birthday=#{birthday},gender=#{gender}, address=#{address} where id=#{id} </update>
第二步:编写单元测试
在 TestEshop 单元测试类中添加单元测试方法,代码如下:
@Test public void testUpdateUserInfo() { // 通过工厂得到 SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 插入用户对象 UserInfoModel model = new UserInfoModel(); model.setId(5); model.setUserName("宋江江"); model.setUserPass("songjiang"); model.setBirthday(new Date()); model.setGender("男"); model.setAddress("山东郓城"); sqlSession.update("eshop.updateUserInfo", model); // 提交事务 sqlSession.commit(); // 关闭会话 sqlSession.close(); }
第三步:单元测试
运行单元测试,控制台输出日志如下
15:50:39,572 DEBUG updateUserInfo:159 - ==> Preparing: update userinfo set userName=?,birthday=?,gender=?,address=? where id=? 15:50:39,619 DEBUG updateUserInfo:159 - ==> Parameters: 宋江江(String), 2017-09-22 15:50:39.322(Timestamp), 男(String), 山东郓城(String), 5(Integer) 15:50:39,619 DEBUG updateUserInfo:159 - <== Updates: 1 15:50:39,619 DEBUG JdbcTransaction:70 - Committing JDBC Connection
- 日志中输出了执行的 sql 语句为 update userinfo set userName=?,birthday=?,gender=?, address=? where id=?
- 传入参数是宋江江(String), 2017-09-22 15:50:39.322(Timestamp), 男(String), 山东郓城(String), 5(Integer)
- 输出结果是:Updates: 1
- 查看数据库,宋江的名字更改为宋江江
- 注意:在更新数据时,被更新的 POJO 对象中必须存在主键值
5.9. 任务 6:删除用户
第一步:创建 Mapped Statement ID
在映射文件 userinfo.xml 中添加 Mapped Statement ID,代码如下:
<delete id="deleteUserInfo" parameterType="java.lang.Integer"> delete from userinfo where id=#{id} </delete>
第二步:编写单元测试
在 TestEshop 单元测试类中添加单元测试方法,代码如下:
@Test public void testDeleteUserInfo() { // 通过工厂得到 SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //传入被删除记录的主键值 5 sqlSession.delete("eshop.deleteUserInfo", 5); // 提交事务 sqlSession.commit(); // 关闭会话 sqlSession.close(); }
第三步:单元测试
运行单元测试,控制台输出日志如下
15:59:12,021 DEBUG deleteUserInfo:159 - ==> Preparing: delete from userinfo where id=? 15:59:12,059 DEBUG deleteUserInfo:159 - ==> Parameters: 5(Integer) 15:59:12,069 DEBUG deleteUserInfo:159 - <== Updates: 1 15:59:12,070 DEBUG JdbcTransaction:70 - Committing JDBC Connection
- 日志中输出了执行的 sql 语句为 delete from userinfo where id=?
- 传入参数是 5(Integer)
- 输出结果是:Updates: 1
- 查看数据库,id=5 的用户被删除
5.10. MyBatis 解决了 JDBC 编程的问题
通过以上对用户的添加、删除、修改、查询的例子,发现 MyBatis 框架让程序开发人员将精力集中在 SQL 本身,而不必将精力放在例如加载驱动、创建 connection、创建 statement、设置参数、结果集检索等 jdbc 繁杂的过程里。解决了 JDBC 编程的问题,具体过程如下:
- 数据库连接对象的创建、释放频繁,造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。在 SqlMapConfig.xml 中配置数据连接池,使用连接池管理数据库连接。
- Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。MyBatis 框架将 Sql 语句配置在映射文件中(mapper.xml)与java 代码分离。
- 传入参数繁琐,SQL 语句的 where 条件中占位符的个数可能会变化,Mybatis 自动将 java对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的类型。
- 对结果集解析繁琐,sql 变化导致解析代码变化,且解析前需要遍历,Mybatis 自动将 sql执行结果映射至 POJO 对象,通过 statement 中的 resultType 定义输出结果的类型。