mybatis错误之配置文件属性配置问题

时间:2022-05-04
本文章向大家介绍mybatis错误之配置文件属性配置问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

在mybatis的配置文件SqlMapConfig.xml中,可以在开始的地方先加载一个properties节点,用来定义属性变量。

1 <!-- 加载属性文件 -->
2     <properties resource="db.properties">
3         <!--properties中还可以配置一些属性名和属性值  -->
4         <!-- <property name="jdbc.driver" value=""/> -->
5     </properties>

然后可以在后面的节点中引用变量:

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=

value=m

SqlMapConfig

 1 <!-- 和spring整合后 environments配置将废除-->
 2     <environments default="development">
 3         <environment id="development">
 4         <!-- 使用jdbc事务管理,事务控制由mybatis-->
 5             <transactionManager type="JDBC" />
 6         <!-- 数据库连接池,由mybatis管理-->
 7             <dataSource type="POOLED">
 8                 <property name="driver" value="${jdbc.driver}" />
 9                 <property name="url" value="${jdbc.url}" />
10                 <property name="username" value="${jdbc.username}" />
11                 <property name="password" value="${jdbc.password}" />
12             </dataSource>
13         </environment>
14     </environments>

但是,这涉及到几个问题,首先就是加载顺序,后者的变量会覆盖先加载的?看教程是这样说的:

properties特性:

 注意:

MyBatis 将按照下面的顺序来加载属性:

      在 properties 元素体内定义的属性首先被读取。

      然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

        最后读取parameterType传递的属性,它会覆盖已读取的同名属性。

 建议:

不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。

      在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX

举例来说:

  1. 在db.properties中定义了value=m
  2. 在mybat配置mapper里,SqlMapConfig.xml中设置mapper文件为:
1     <!-- 加载 映射文件 -->
2     <mappers>
3         <mapper resource="mapper/UserMapper.xml"/>
4     </mappers>

    3. 编写接口:UserMapper.java

 1 package cn.mrf.mybatis.mapper;
 2 
 3 
 4 import java.util.List;
 5 
 6 import cn.mrf.mybatis.po.User;
 7 
 8 /**
 9  * 
10 * @ClassName: UserDao 
11 * @Description: mapper接口:用户管理 
12 * @author mrf
13 * @date 2015-9-19 下午05:48:49 
14 *
15  */
16 public interface UserMapper {
17     
18     
19     //根据id查询用户信息
20     public User findUserById(int id) throws Exception;
21     
22     //根据用户名查询用户列表
23     public List<User> findUserByName(String name) throws Exception;
24     
25     //添加用户信息
26     public void insertUser(User user) throws Exception;
27     
28     //删除用户信息
29     public void deleteUser(int id) throws Exception;
30     
31     //更新用户信息
32     public void updateUser(User user) throws Exception;
33     
34 }

 4. 配置UserMapper.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper
 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 
 6 <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 
 7 注意:使用mapper代理方法开发,namespace有特殊重要的作用
 8 -->
 9 <mapper namespace="cn.mrf.mybatis.mapper.UserMapper">
10 
11     <!-- 在 映射文件中配置很多sql语句 -->
12     <!-- 需求:通过id查询用户表的记录 -->
13     <!-- 通过 select执行数据库查询
14     id:标识 映射文件中的 sql
15     将sql语句封装到mappedStatement对象中,所以将id称为statement的id
16     parameterType:指定输入 参数的类型,这里指定int型 
17     #{}表示一个占位符号
18     #{id}:其中的id表示接收输入 的参数,参数名称就是id,如果输入 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称
19     
20     resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。
21      -->
22     <select id="findUserById" parameterType="int" resultType="cn.mrf.mybatis.po.User">
23         SELECT * FROM USER WHERE id=#{value}
24     </select>
25     
26     <!-- 根据用户名称模糊查询用户信息,可能返回多条
27     resultType:指定就是单条记录所映射的java对象 类型
28     ${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。
29     使用${}拼接sql,引起 sql注入
30     ${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value
31      -->
32     <select id="findUserByName" parameterType="java.lang.String" resultType="cn.mrf.mybatis.po.User">
33         SELECT * FROM USER WHERE username LIKE '%${value}%'
34     </select>
35 </mapper>

 5. 编写mapper代理测试用例UserMapperTest.java

 1 package cn.mrf.mybatis.mapper;
 2 
 3 
 4 import java.io.InputStream;
 5 import java.util.List;
 6 
 7 import org.apache.ibatis.io.Resources;
 8 import org.apache.ibatis.session.SqlSession;
 9 import org.apache.ibatis.session.SqlSessionFactory;
10 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
11 import org.junit.Before;
12 import org.junit.Test;
13 
14 import cn.mrf.mybatis.po.User;
15 
16 import com.sun.istack.internal.Builder;
17 
18 public class UserMapperTest {
19 
20     private SqlSessionFactory sqlSessionFactory;
21     
22     @Before
23     public void setUp() throws Exception {
24         // 创建sqlSessionFactory
25         // mybatis配置文件
26         String resource = "SqlMapConfig.xml";
27         // 得到配置文件流
28         InputStream inputStream = Resources.getResourceAsStream(resource);
29         // 创建会话工厂,传入mybatis的配置文件信息
30         sqlSessionFactory = new SqlSessionFactoryBuilder()
31                 .build(inputStream);
32         
33     }
34     
35     @Test
36     public void testFindUserByName() throws Exception{
37         SqlSession sqlSession = sqlSessionFactory.openSession();
38         UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
39         List<User> users = userMapper.findUserByName("小军");
40         System.out.println(users);
41         sqlSession.close();
42         
43     }
44     
45 }

5.结果:

 1 DEBUG [main] - Opening JDBC Connection
 2 DEBUG [main] - Created connection 423250256.
 3 DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@193a4950]
 4 DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE username LIKE '%m%' 
 5 DEBUG [main] - ==> Parameters: 
 6 DEBUG [main] - <==      Total: 1
 7 [User [id=1, username=mrf, sex=男, birthday=Sat Feb 23 00:00:00 CST 1991, address=北京]]
 8 DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@193a4950]
 9 DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@193a4950]
10 DEBUG [main] - Returned connection 423250256 to pool.

6.分析:

  可以看出,本来是根据用户名查找用户,输入了用户名为小军,而实际上,系统读取的用户名为m.

  也就是说,系统没有读取parameterType的值,或者被覆盖。

  那么,问题是,教程说最后读取parameterType并覆盖、如果这样,最后应该读取的小军才对。实际却是m.顺序有疑问了。

  好吧,因为parameterType中并没有这个值,所以没有覆盖。