9.4 深入Mapper XML映射文件 示例 测试select,insert,update和delete操作 本示例直接使用第8章创建的TB_USER
表,数据库脚本,User.java
和log4j.xml
,具体请参考第8章内容,此处不再赘述。 在实际项目开发中,连接数据库的参数信息不会直接写在mybatis-config.xml
中,而是通过一个properties
文件来定义连接数据库的参数信息,并在mybatis-config.xml
中引用。
项目结构 展开/折叠
D:\Desktop\随书源码\Spring+Mybatis企业应用实战(第2版)\codes\09\DMLTest
├─src\
│ ├─db.properties
│ ├─log4j.xml
│ ├─mybatis-config.xml
│ └─org\
│ └─fkit\
│ ├─domain\
│ │ └─User.java
│ ├─factory\
│ │ └─FKSqlSessionFactory.java
│ ├─mapper\
│ │ └─UserMapper.xml
│ └─test\
│ ├─DeleteTest.java
│ ├─InsertTest.java
│ ├─SelectTest.java
│ └─UpadeTest.java
└─WebContent\
├─META-INF\
│ └─MANIFEST.MF
└─WEB-INF\
├─lib\
│ ├─ant-1.9.6.jar
│ ├─ant-launcher-1.9.6.jar
│ ├─asm-5.2.jar
│ ├─cglib-3.2.5.jar
│ ├─commons-logging-1.2.jar
│ ├─javassist-3.22.0-CR2.jar
│ ├─log4j-1.2.17.jar
│ ├─log4j-api-2.3.jar
│ ├─log4j-core-2.3.jar
│ ├─mybatis-3.4.5.jar
│ ├─mysql-connector-java-5.1.44-bin.jar
│ ├─ognl-3.1.15.jar
│ ├─slf4j-api-1.7.25.jar
│ └─slf4j-log4j12-1.7.25.jar
└─web.xml
db.properties 1 2 3 4 driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/mybatis username=root password=root
mybatis-config.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <properties resource ="db.properties" /> <settings > <setting name ="logImpl" value ="LOG4J" /> </settings > <typeAliases > <typeAlias alias ="user" type ="org.fkit.domain.User" /> </typeAliases > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${driver}" /> <property name ="url" value ="${url}" /> <property name ="username" value ="${username}" /> <property name ="password" value ="${password}" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="org/fkit/mapper/UserMapper.xml" /> </mappers > </configuration >
引入properties配置文件 mybatis-config.xml
中的
1 <properties resource ="db.properties" />
配置表示引入db.properties
资源配置文件,
1 2 3 <property name ="driver" value ="${driver}" />
引用properties配置文件中的值 表示driver
的值引用db.properties
文件中的名称为driver
的值com.mysql.jdbc.Driver
。 同理:
1 2 3 ${url} ${username} ${password}
引用db.properties
文件中对应的url
,username
和password
的值。
UserMapper.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?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 ="org.fkit.mapper.UserMapper" > <insert id ="saveUser" parameterType ="user" useGeneratedKeys ="true" keyProperty ="id" > insert into tb_user(name,sex,age) values(#{name},#{sex},#{age}) </insert > <select id ="selectUser" parameterType ="int" resultType ="user" > select * from tb_user where id = #{id} </select > <update id ="modifyUser" parameterType ="user" > update tb_user set name = #{name},sex = #{sex},age = #{age} where id = #{id} </update > <delete id ="removeUser" parameterType ="int" > delete from tb_user where id = #{id} </delete > </mapper >
在UserMapper.xml
中定义了insert
、update
、delete
和select
4个元素,分别对应插入、更新、删除和查询4个数据库操作。
FKSqlSessionFactory.java 因为每次测试都需要读取mybatis-config.xml
根配置文件,根据根配置文件信息创建SqlSessionFactory
对象,再获取Sqlsession
对象,使得该操作比较频繁,所以开发一个FKSqlSessionFactory
工厂类封装以上操作的重复代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package org.fkit.factory;import java.io.InputStream;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class FKSqlSessionFactory { private static SqlSessionFactory sqlSessionFactory = null ; static { try ( InputStream is = Resources .getResourceAsStream("mybatis-config.xml" )) { sqlSessionFactory = new SqlSessionFactoryBuilder ().build(is); } catch (Exception e) { e.printStackTrace(); } } public static SqlSession getSqlSession () { return sqlSessionFactory.openSession(); } public static SqlSessionFactory getSqlSessionFactory () { return sqlSessionFactory; } }
测试insert标签 InsertTest.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class InsertTest { public static void main (String[] args) { SqlSession sqlSession = null ; try { sqlSession = FKSqlSessionFactory.getSqlSession(); User user = new User ("jack" , "男" , 22 ); sqlSession.insert("org.fkit.mapper.UserMapper.saveUser" , user); sqlSession.commit(); } catch (Exception e) { sqlSession.rollback(); e.printStackTrace(); } finally { if (sqlSession != null ) sqlSession.close(); } } }
运行InsertTest
类的main
方法,创建User
对象,并将User
对象作为参数调sqlSession
的insert
方法,
Mybatis如何找到要执行的SQL语句 insert
方法的第一个参数是org.fkit.mapper.UserMapper.saveUser
,MyBatis
会找到org.fkit.mapper.UserMapper
命名空间下id="saveUser"
元素,执行该元素中的SQL
语句。
1 2 3 4 5 6 7 8 9 10 11 <mapper namespace ="org.fkit.mapper.UserMapper" > ...... <insert id ="saveUser" parameterType ="user" useGeneratedKeys ="true" keyProperty ="id" > insert into tb_user(name,sex,age) values(#{name},#{sex},#{age}) </insert > ...... </mapper >
insert元素属性解释 insert
元素的属性:
parameterType="user"
表示该插入语句需要一个User
对象作为参数
useGeneratedKeys="true"
表示使用数据库的自动增长的主键,该操作需要底层数据库的支持;
keyProperty="id"
表示将插入数据生成的主键设置到user
对象的id
当中。
MyBatis表达式 insert
元素中的SQL
语句是一条标准的insert into
语句,需要注意的是,#{name}
使用了MyBatis
的表达式,其会查找参数user
当中的name
属性作为值,并将该值设置到SQL
语句中 ;如果传入的参数是一个Map
,则会以name
作为key
查找Map
当中的值,并将该值设置到SQL
语句中 。#{sex}
、#{age}
和#{name}
操作相同. 运行InsertTest
类的main
方法,将会插入一条数据到数据库当中。控制台结果如下所示:
1 2 3 DEBUG [main] ==> Preparing: insert into tb_user(name,sex,age) values(?,?,?) DEBUG [main] ==> Parameters: jack(String), 男(String), 22 (Integer) DEBUG [main] <== Updates: 1
插入数据后数据库表中的数据如下图所示:
测试select标签 SelectTest.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class SelectTest { public static void main (String[] args) { SqlSession sqlSession = null ; try { sqlSession = FKSqlSessionFactory.getSqlSession(); User user = sqlSession.selectOne("org.fkit.mapper.UserMapper.selectUser" , 1 ); System.out.println(user); sqlSession.commit(); } catch (Exception e) { sqlSession.rollback(); e.printStackTrace(); } finally { if (sqlSession != null ) sqlSession.close(); } } }
如何找到要执行的SQL语句 运行SelectTest
类的main
方法,调用SqlSession
的 selectOne
方法, selectOne
方法的第个参数是org.fkit.mapper.UserMapper.selectUser
, MyBatis
会找到org.fkit.mapper.UserMapper
命名空间下id="selectUser"
的元素,执行该元素中的SQL
语句:
1 2 3 4 5 6 7 8 9 10 <mapper namespace ="org.fkit.mapper.UserMapper" > ...... <select id ="selectUser" parameterType ="int" resultType ="user" > select * from tb_user where id = #{id} </select > ...... </mapper >
属性解释 select
元素中的
parameterType="int"
表示该插入新语句需要一个int
类型的值作为参数;
resultType="user"
表示该条查询语句需要返回一个User
对象。
元素中的SQL
语句是一条标准的select
语句,该语句需要的参数id
的值,就是我们是调用时传入的int
值。
运行效果 运行SelectTest
类的main
方法,程序将会到数据库当中查询id
为1的一条数据并封装成User
类型的对象返回。控制台结果如下所示:
1 2 3 4 DEBUG [main] ==> Preparing: select * from tb_user where id = ? DEBUG [main] ==> Parameters: 1 (Integer) DEBUG [main] <== Total: 1 User [id=1 , name=admin, sex=男, age=26 ]
测试update元素 UpadeTest.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class UpadeTest { public static void main (String[] args) { SqlSession sqlSession = null ; try { sqlSession = FKSqlSessionFactory.getSqlSession(); User user = sqlSession.selectOne("org.fkit.mapper.UserMapper.selectUser" , 1 ); user.setName("tom" ); user.setAge(25 ); sqlSession.update("org.fkit.mapper.UserMapper.modifyUser" , user); sqlSession.commit(); } catch (Exception e) { sqlSession.rollback(); e.printStackTrace(); } finally { if (sqlSession != null ) sqlSession.close(); } } }
运行UpdateTest
类的main
方法,首先调用SqlSession
的selectOne
方法,查询出id
为1
的数据返回给User
对象。接下来修改该User
对象的属性值,最后调用SqlSession
的update
方法修改该User
对象。update
方法的第一个参数是org.fkit.mapper.UserMapper.modifyUser
,MyBatis
会找到org.fkit.mapper.UserMapper
命名空间下id="modifyUser"
的元素,执行该元素中的SQL
语句。
1 2 3 4 5 6 7 8 9 <mapper namespace ="org.fkit.mapper.UserMapper" > ...... <update id ="modifyUser" parameterType ="user" > update tb_user set name = #{name},sex = #{sex},age=#{age} where id = #{id} </update > ...... </mapper >
update
元素的属性:parameterType="user"
表示该更新语句需要一个User
对象作为参数。
update
元素中的SQL
语句是一条标准的update
语句,该语句根据传入的User
对象的属性更新表数据。
运行效果 运行UpdateTest
类的main
方法,我们将会看到数据库中的更新数据。控制台结果如下所示:
1 2 3 4 5 6 DEBUG [main] ==> Preparing: select * from tb_user where id = ? DEBUG [main] ==> Parameters: 1 (Integer) DEBUG [main] <== Total: 1 DEBUG [main] ==> Preparing: update tb_user set name = ?,sex = ?,age = ? where id = ? DEBUG [main] ==> Parameters: tom(String), 男(String), 25 (Integer), 1 (Integer) DEBUG [main] <== Updates: 1
更新数据后数据库表数据如下图所示:
测试delete元素 DeleteTest.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class DeleteTest { public static void main (String[] args) { SqlSession sqlSession = null ; try { sqlSession = FKSqlSessionFactory.getSqlSession(); sqlSession.delete("org.fkit.mapper.UserMapper.removeUser" , 1 ); sqlSession.commit(); } catch (Exception e) { sqlSession.rollback(); e.printStackTrace(); } finally { if (sqlSession != null ) sqlSession.close(); } } }
运行DeleteTest
类的main
方法,调用SqlSession
的delete
方法。delete
方法的第一个参数是org.fkit.mapper.UserMapper.removeUser
,MyBatis
会找到org.fkit.mapper.UserMapper
命名空间下的 id="removeUser"
的元素,执行该元素中的SQL
语句:
1 2 3 4 5 6 7 8 <mapper namespace ="org.fkit.mapper.UserMapper" > ...... <delete id ="removeUser" parameterType ="int" > delete from tb_user where id = #{id} </delete > ...... </mapper >
delete
元素中的parameterType="int"
表示该删除语句需要一个int
类型的值作为参数。
元素中的SQL
语句是一条标准的delete
语句,该语句需要的参数id
值是调用时传入的int
值。
运行结果 1 2 3 DEBUG [main] ==> Preparing: delete from tb_user where id = ? DEBUG [main] ==> Parameters: 1(Integer) DEBUG [main] <== Updates: 1
删除后数据库表数据如下图所示: