MyBatista框架进行CRUD的操作
-
Mybatis环境搭建的步骤:
- 首先是创建一个Maven工程
- 导入相应坐标
- 编写实体类和持久层的接口例如:User实体类和 UserDao的持久层接口
- 编写主配置文件SqlMapConfig.xml
- 编写映射配置文件例如:UserDao.xml
- 编写测试类
-
SqlMapConfig.xml文件中的配置内容和顺序
- 创建SqlMapConfig.xml文件来导入相应的约束 mybatis中使用的约束类型是DTD类型的约束,而不是scame类型的约束。
- 使用代理dao实现CRUD操作的要求:
- 持久层接口和持久层接口必须有相同的包结构。
- 持久层映射配置文件中的mapper标签中的namespace属性必须是持久层接口的全限定类名。
- sql语句中的配置标签如<select><insert><update><delete>的id属性必须和持久层接口的方法名称相同。【只有实现了上述的要求才能不用创建持久层接口的实现类而是由mybatis框架来实现】
-
CRUD 操作的实现【基于的是xml配置】
- 查询用户的操作:
- 根据用户的id来查询用户的信息 :findByUserId方法
-
在持久层接口中添加findByUserid方法 返回的是一个user对象。参数类型是Integer类型
User findByUserId(Integer userId);
-
在用户的映射配置文件中进行配置:
<!-- 根据 id 查询 --> <select id="findById" resultType="com.itheima.domain.User" parameterType="int"> <!-这里的参数传递使用的#{}和${}都行但是两者的区别在后面会详细的解释--> select * from user where id = #{uid} </select>
-
配置的细节:id属性:“指定的是持久层接口的方法名称 resultType:指的就是要封装的结果集类型 User的全限定类名 parameterType:指的就是参数的类型 就是java.lang.Integer 或者也能写成Integer(可以不写全限定类名的原因是起了别名 之后再详细的解释)
-
进行测试:
-
参数传递中的#{} 和 ${}
- #{}:表示的是一个占位符号,相当于jdbc中preparedStatement中参数传递的?能自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{}括号中可以是 value 或其它名称。
- ${}:会将传入的数据直接的显示在生成的SQL语句中,进行SQL的拼接。会可能造成SQL注入的问题。同时不进行SQL的预编译,所以从安全性和性能的角度出发,能使用#{}的情况下就不要使用${}。 ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。
-
- 根根据用户的名称来进行模糊查询用户的信息:findUserByName方法
- 在持久层接口中添加findUserByName方法 返回的是一个user对象。参数类型是String类型List<User> findUserByName(String username);
- 在用户的映射配置文件中进行配置:
<!-- 根据名称模糊查询 --> <select id="findUserByName" resultType="com.itheima.domain.User" parameterType="String"> select * from user where username like #{username} </select>
- 细节:
- 我们在配置文件中没有加入%来作为模糊查询的条件,所以在传入字符串实参时,就需要给定模糊查询的标识%。配置文件中的#{username}也只是一个占位符,所以 SQL 语句显示为“select * from user where username like ?”。
- 模糊查询的另一种方式:就是讲以前的SQL语句中的#{username}改为 ‘%${value}%’ 但是需要注意的是:用模糊查询的这种写法,那么${value}的写法就是固定的,不能写成其它名字。而且在使用时不需要传递匹配符%了,这两种方式实现的效果是一致的 但是执行的SQL语句不是一样的。
- 使用聚合函数来查询:
- 在持久层接口上添加 findTotal 方法 返回值类型是int类型,表示的是user表中总用户数
int findTotal()
- 在用户的映射配置文件中进行配置:
<!-- 查询总记录条数 --> <select id="findTotal" resultType="int"> select count(*) from user; </select>
- 进行测试:输出的用户的数量是6
- 在持久层接口上添加 findTotal 方法 返回值类型是int类型,表示的是user表中总用户数
- 根据用户的id来查询用户的信息 :findByUserId方法
- 保存用户的操作:
- 保存用户的信息:saveUser 方法
-
在持久层接口中添加saveUser 方法 返回的是一个user对象。参数类型是User类型
void saveUSer(User user);
-
在用户的映射配置文件中进行配置
<!--用户的保存方法--> <insert id="saveUSer" parameterType="com.itheima.domain.User"> insert into user(username, birthday, sex, address) values(#{username},#{birthday},#{sex},#{address}) </insert>
-
配置的细节:#{}中的内容的写法:保存方法中参数是一个user对象,而此处需要的是user对象中的属性名称,因此需要使用的是ognl表达式:
- ognl 表达式: 它是 apache 提供的一种表达式语言,全称是:Object Graphic Navigation Language 【对象图导航语言】它是按照一定的语法格式来获取数据的。语法格式就是使用 #{对象.对象}的方式 #{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user.而直接写 username。
-
进行测试:junit中显示成功 但是数据库中并没有添加任何记录
-
方法执行成功但是没有记录的添加原因是:从jdbc中的学习可知,数据库的增删改是需要控制事务的提交,但是在Mybatis中怎么控制事务的提交。在Mybatis中控制事务提交的方式有两种:
- 在使用工厂来生产session对象的时候使用的openSession方法的重载形式: 一种是没有参数;另一种是设置自动提交 使用openSession(true) 来设置自动提交
- 另一种方式:在执行操作完成之后使用session.commit 方法手动的进行提交。
- 在使用工厂来生产session对象的时候使用的openSession方法的重载形式: 一种是没有参数;另一种是设置自动提交 使用openSession(true) 来设置自动提交
-
再次查看结果:数据库中新用户添加成功
-
保存用户成功需要将新插入的用户的id 返回:但是用户的id是有数据库自动增长的来的,需要将自动增长后的auto_increment的值返回。这样的方式不只适用支持主键自增的数据库 也适用序列得到值(如Oracle) 需要注意的是:Oracle中的INSERT 语句中必须明确写出id值 和 #id 方法就是:
<insert id="saveUser" parameterType="com.itheima.domain.user"> <!-- 配置保存时获取插入的 id --> <selectKey keyColumn="id" keyProperty="id" resultType="int"> select last_insert_id(); </selectKey> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert>
其他些支持主键自增的数据库配置 selectKey中回写主键的 SQL
DB2 使用 VALUES IDENTITY VAL LOCAL () MYSQL 使用 SELECT LAST_INSERT_ID () SQLSERVER 使用 SELECT SCOPE IDENTITY () CLOUDSCAPE 使用 VALUES IDENTITY VAL LOCAL () DERBY 使用 VALUES IDENTITY VAL LOCAL () HSQLDB 使用 CALL IDENTITY () SYBASE 使用 SELECT @@IDENTITY DB2 MF 使用 SELECT IDENTITY VAL LOCAL(} FROM SYSIBM. SYSDUMMYl FORMIX 使用 select dbinfo ('sq lea. sqlerrdl ’ ) from systables where tabid=1 ORACLE 使用 SELECT SEQ ID.nextval from dual
- 使用的标签和属性:
- 想要获取id:使用的是selectKey 标签
- selectKey标签的属性:四种常用的属性
- keyColmun 要获取哪一列的数据(哪一列的数据是id)
- keyProperty 要把该属性(id)赋值给哪个字段
- resultType 返回类型
- order 是在插入前获得还是插入后获得
- 使用的标签和属性:
-
另一种获取主键自增的值的方式:
useGeneratedKeys
设置为 true 后, MyBatis 会使用 JDBCgetGeneratedKeys
方法来取出 由数据库内部生成的主键。获得主键值后将其赋值给keyProperty
配置的 id 属性当需要设置多个属性时,使用逗号隔开<insert id=” insert2 ” useGeneratedKeys=” true ” keyProperty=” id” >
-
- 保存用户的信息:saveUser 方法
- 更新用户的操作:
- 更新用户的信息:updateUser方法
- 在持久层接口中添加updateUser方法 返回的类型是int类型 表示的是受影响的行数 参数类型是User类型
int updateUser(User user);
- 在用户的映射配置文件中进行配置
<!-- 更新用户 --> <update id="updateUser" parameterType="com.itheima.domain.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update>
- 在用户的映射配置文件中进行配置
- 进行测试:执行成功 用户的信息进行了修改
- 删除用户的操作:
- 删除用户的信息:deleteUser方法 通过的是用户的id来进行用户的删除
- 在持久层接口中添加deleteUser方法 返回的类型是int类型 表示的是受影响的行数 参数类型是int类型
int updateUser(Integer id);
- 在用户的映射配置文件中进行配置
<!-- 删除用户 --> <delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id = #{uid} </delete>
- 在用户的映射配置文件中进行配置
- 查询用户的操作:
-
Mybatis和传统的jdbc的比较:
- 传统的jdbc方式数据库连接的频繁创建和释放会造成系统资源的浪费从而影响系统的性能。在mybatis中使用数据库库连接池的技术能够解决此问题。
- 传统的jdbc操作SQL语句写在代码中,造成的后果就是代码的维护困难,但是实际的生产中,SQL变动的情况非常的常见,而在mybatis中使用配置文件xxxMapper.xml实现java代码和SQL语句的分离能很好的解决此问题。
- 传统的jdbc对结果集的封装非常的麻烦,但是使用mybatis对结果集的封装十分的简便。只需要指定结果集的类型 就能够进行自动的封装。
【总结】Mybatis能使人们更加的关注SQL语句的编写,而数据库中建立连接、释放连接和结果集的封装等操作Mybatis会帮助你完成 从而使人们的开发效率得到大大的提升。