1、持久层接口和持久层接口的映射配置必须在相同的包下
2、持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名
3、SQL 语句的配置标签<select>,<insert>,<delete>,<update>的 id 属性必须和持久层接口的 方法名相同。
public interface IUserDao { /** * 根据id查询 */ User findById(Integer uid); /** * 保存用户 */ void saveUser(User user); /** * 更新用户 */ void updateUser(User user); /** * 根据id删除用户 */ void deleteUser(Integer uid);//这里的返回值类型是void还是int,影响不大,同上 /** * 根据名称模糊查询 */ List<User> findByName(String username); /** * 查询总记录条数 */ int findTotal(); }
<?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.churujianghudezai.dao.IUserDao"> <!--这里的id值直接和接口里的方法名对应--> <!--根据id查询--> <select id="findById" parameterType="int" resultType="com.churujianghudezai.domain.User"> select * from user where id = #{uid} </select> <!--保存用户,并返回保存后该用户对应的id--> <insert id="saveUser" parameterType="com.churujianghudezai.domain.User"> <!--配置时保存获取插入的id AFTER:此语句在插入语句之后执行 (可不写) keyColumn="id":keyColumn用于指定数据库表user中的主键(可不写) keyProperty="id": 此语句返回值要传递给当前方法参数中的id属性 (com.churujianghudezai.domain.User的id属性)(不可省) resultType=“int”: 此语句执行后的返回类型是 int keyProperty和resultType必不可少,且要相互对应才行--> <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> <!--更新用户,这里以更新用户名为例--> <update id="updateUser" parameterType="com.churujianghudezai.domain.User"> update user set username=#{username} where id=#{id} </update> <!--删除用户--> <delete id="deleteUser" parameterType="int"> delete from user where id = #{id} </delete> <!--根据名称模糊查询--> <select id="findByName" resultType="com.churujianghudezai.domain.User" parameterType="String"> select * from user where username like #{username}/* 此处也可以写成 like ‘%${value}%‘ */ </select> <!--查询总记录条数--> <select id="findTotal" resultType="int"> select count(*) from user </select> </mapper>
细节:
resultType 属性:
用于指定结果集的类型。 当结果类型为实体类时,这就要求该类中的属性名与数据库表中字段名保持一致(可以不区分大小写)(请看下一章博客内容:mybatis参数深入)
parameterType 属性:
用于指定传入参数的类型,需要注意的是:
1.若参数类型写成User类,那么该参数名得要写成该类中对应的属性名,如:
parameterType="com.churujianghudezai.domain.User" update user set username=#{username} where id=#{id} 这里id不能写成userid、uid,username不能写成name等
它用的是 ognl 表达式。
ognl 表达式:它是 apache 提供的一种表达式语言,全称是:Object Graphic Navigation Language 对象图导航语言 它是按照一定的语法格式来获取数据的。
(语法格式就是使用 #{对象.对象}的方式 :#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用 getUsername()方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user. 而直接写 username。)
2.若参数类型是基本数据类型或String,则参数名可以随意起,如:
parameterType="int" select * from user where id = #{uid} 这里参数类型定义的是int,不是User,所以该参数名可以随便起,如userid等
(因为这条是查询语句,有返回结果,且该结果类型为user类,这就要求该类中属性名与数据表中字段名一致)
sql 语句中使用#{}字符:
它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。
#{}与${}的区别:
#{}表示一个占位符号 通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换, #{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类 型值,#{}括号中可以是 value 或其它名称。
${}表示拼接 sql 串 通过${}可以将 parameterType 传入的内容拼接在 sql中且不进行 jdbc 类型转换, ${}可以接收简 单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。
public class MybatisCRUDTest { private InputStream in; private SqlSessionFactory factory; private SqlSession session; private IUserDao userDao; @Test public void testFindOne(){ //6.执行操作 User user = userDao.findById(41); System.out.println(user); } @Test public void testSaveUser(){ User user = new User(); user.setUsername("赵本山"); user.setSex("男"); user.setBirthday(new Date()); user.setAddress("辽宁铁岭"); System.out.println("保存操作之前:"+user.getId()); userDao.saveUser(user); //在dao操作完成后,直接调用getId()就可获得用户保存后对应的自增id System.out.println("保存操作完成,获得的id为"+user.getId()); } @Test public void testUpdateUser(){ User user = userDao.findById(59); user.setUsername("小飞侠"); userDao.updateUser(user); user = userDao.findById(59); System.out.println(user); } @Test public void testDeleteUser(){ userDao.deleteUser(58); } @Test public void testFindByName(){ /*xml文件中使用%${value}%方式配置时,这里的参数只要写成 “王” 即可*/ List<User> users = userDao.findByName("%王%"); for (User user:users){ System.out.println(user); } } @Test public void testFindTotal(){ int num = userDao.findTotal(); System.out.println(num); } @Before//在测试方法执行前执行 public void init() throws Exception{ //1.读取配置文件 in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.创建构建者对象 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //3.创建SqlSession工厂对象 factory = builder.build(in); //4.创建SqlSession对象 session = factory.openSession(); //5.创建Dao的代理对象 userDao = session.getMapper(IUserDao.class); } @After//测试方法执行完成之后执行 public void destroy() throws Exception{ //7.提交事务 session.commit(); //8.释放资源 session.close(); in.close(); } }
1.数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决: 在 SqlMapConfig.xml 中配置数据链接池,使用连接池管理数据库链接。
2.Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
解决: 将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
3.向sql语句传参数麻烦,因为sql语句的where 条件不一定,可能多也可能少,占位符需要和参数对应。
解决: Mybatis自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的 类型。
4.对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对 象解析比较方便。
解决: Mybatis自动将 sql执行结果映射至 java 对象,通过statement中的resultType 定义输出结果的 类型。
mybatis学习——基于代理 Dao 实现 CRUD 操作
原文:https://www.cnblogs.com/churujianghudezai/p/12211547.html