接下来我们来实现新增用户功能:
一、新增用户
这里我们使用的sql为:insert into user(username,birthday,sex,address) values ("lwj","2018-01-26","2","南天门");
1.1 在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 <!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 --> 6 <mapper namespace="user"> 7 <!-- id:statement的id 或者叫做sql的id--> 8 <!-- parameterType:声明输入参数的类型 --> 9 <!-- resultType:声明输出结果的类型,应该填写pojo的全路径 --> 10 <!-- #{}:输入参数的占位符,相当于jdbc的? --> 11 12 <!--根据id查询用户信息 --> 13 <select id="findUserById" parameterType="Integer" resultType="com.lwjnicole.pojo.User"> 14 select * from user where id = #{v} 15 </select> 16 17 <!--如果返回多个结果,mybatis会自动把返回的结果放在list容器中 --> 18 <!--resultType的配置和返回一个结果的配置一样 --> 19 <!--实现功能 :根据用户名模糊查询用户列表 --> 20 <select id="findUserByUsername" parameterType="String" resultType="com.lwjnicole.pojo.User"> 21 select * from user where username like '%${value}%' 22 </select> 23 24 <!--实现功能:新增用户 --> 25 <insert id="insertUser" parameterType="com.lwjnicole.pojo.User"> 26 insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}); 27 </insert> 28 </mapper>
1.2 在Test类中新增Junit测试代码:
1 package mybatis_study; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.Date; 6 import java.util.List; 7 8 import org.apache.ibatis.io.Resources; 9 import org.apache.ibatis.session.SqlSession; 10 import org.apache.ibatis.session.SqlSessionFactory; 11 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 12 import org.junit.After; 13 import org.junit.Before; 14 15 import com.lwjnicole.pojo.User; 16 17 public class Test { 18 private SqlSessionFactory sqlSessionFactory = null; 19 private SqlSession session = null; 20 21 @Before 22 public void before(){ 23 //创建SqlSessionFactoryBuilder对象 24 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); 25 InputStream inputStream = null; 26 try { 27 //加载SqlMapConfig.xml配置文件 28 inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 29 } catch (IOException e) { 30 e.printStackTrace(); 31 } 32 //创建SqlSessionFactory对象 33 this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); 34 } 35 36 //新增用户 37 @org.junit.Test 38 public void insertUser(){ 39 //创建SqlSession对象 40 session = sqlSessionFactory.openSession(); 41 //创建需要新增的User对象 42 User user = new User(); 43 user.setUsername("lwj"); 44 user.setBirthday(new Date()); 45 user.setSex("2"); 46 user.setAddress("南天门"); 47 //执行新增操作 48 session.insert("insertUser", user); 49 System.out.println(user); 50 //提交事务 51 session.commit(); 52 } 53 54 @After 55 public void after(){ 56 //释放资源 57 session.close(); 58 } 59 }
1.3 执行结果为:
保存成功,这里我们注意到上面的 id 字段值为 0,那么接下来我们来解决id=0 的问题。
二、mysql 的自增主键返回
查询自增主键的sql为:SELECT LAST_INSERT_ID();
我们只需要修改 userMapper.xml 映射文件就可以将主键返回,添加 selectKey 标签:
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 <!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 --> 6 <mapper namespace="user"> 7 <!-- id:statement的id 或者叫做sql的id--> 8 <!-- parameterType:声明输入参数的类型 --> 9 <!-- resultType:声明输出结果的类型,应该填写pojo的全路径 --> 10 <!-- #{}:输入参数的占位符,相当于jdbc的? --> 11 12 <!--根据id查询用户信息 --> 13 <select id="findUserById" parameterType="Integer" resultType="com.lwjnicole.pojo.User"> 14 select * from user where id = #{v} 15 </select> 16 17 <!--如果返回多个结果,mybatis会自动把返回的结果放在list容器中 --> 18 <!--resultType的配置和返回一个结果的配置一样 --> 19 <!--实现功能 :根据用户名模糊查询用户列表 --> 20 <select id="findUserByUsername" parameterType="String" resultType="com.lwjnicole.pojo.User"> 21 select * from user where username like '%${value}%' 22 </select> 23 24 <!--实现功能:新增用户 --> 25 <insert id="insertUser" parameterType="com.lwjnicole.pojo.User"> 26 <!--selectKey 标签实现主键返回 --> 27 <!--keyColumn :主键对应数据库表中的哪一列 --> 28 <!--keyProperty :主键对应pojo中的哪一个属性 --> 29 <!--order :设置在执行insert语句之前执行查询id的sql,还是在执行insert语句之后执行查询id的sql --> 30 <!--resultType:设置返回id的类型 --> 31 <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int"> 32 SELECT LAST_INSERT_ID() 33 </selectKey> 34 insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}); 35 </insert> 36 </mapper>
LAST_INSERT_ID() 是mysql的函数,返回auto_increment自增列新记录id值。
修改userMapper.xml映射文件后的执行结果为:
上面我们可以看到 id的值已经出来了,如果后续操作需要id参数,那么就可以这样来使用啦!
三、修改用户
3.1 在 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 <!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 --> 6 <mapper namespace="user"> 7 <!-- id:statement的id 或者叫做sql的id--> 8 <!-- parameterType:声明输入参数的类型 --> 9 <!-- resultType:声明输出结果的类型,应该填写pojo的全路径 --> 10 <!-- #{}:输入参数的占位符,相当于jdbc的? --> 11 12 <!--根据id查询用户信息 --> 13 <select id="findUserById" parameterType="Integer" resultType="com.lwjnicole.pojo.User"> 14 select * from user where id = #{v} 15 </select> 16 17 <!--如果返回多个结果,mybatis会自动把返回的结果放在list容器中 --> 18 <!--resultType的配置和返回一个结果的配置一样 --> 19 <!--实现功能 :根据用户名模糊查询用户列表 --> 20 <select id="findUserByUsername" parameterType="String" resultType="com.lwjnicole.pojo.User"> 21 select * from user where username like '%${value}%' 22 </select> 23 24 <!--实现功能:新增用户 --> 25 <insert id="insertUser" parameterType="com.lwjnicole.pojo.User"> 26 <!--selectKey 标签实现主键返回 --> 27 <!--keyColumn :主键对应数据库表中的哪一列 --> 28 <!--keyProperty :主键对应pojo中的哪一个属性 --> 29 <!--order :设置在执行insert语句之前执行查询id的sql,还是在执行insert语句之后执行查询id的sql --> 30 <!--resultType:设置返回id的类型 --> 31 <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int"> 32 SELECT LAST_INSERT_ID() 33 </selectKey> 34 insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}); 35 </insert> 36 37 <!--实现功能:修改用户 --> 38 <update id="updateUser" parameterType="com.lwjnicole.pojo.User"> 39 update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} 40 </update> 41 </mapper>
3.2 Test类中新增Junit测试代码如下:
1 package mybatis_study; 2 3 import static org.junit.Assert.*; 4 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.util.Date; 8 import java.util.List; 9 10 import org.apache.ibatis.io.Resources; 11 import org.apache.ibatis.session.SqlSession; 12 import org.apache.ibatis.session.SqlSessionFactory; 13 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 14 import org.junit.After; 15 import org.junit.Before; 16 17 import com.lwjnicole.pojo.User; 18 19 public class Test { 20 private SqlSessionFactory sqlSessionFactory = null; 21 private SqlSession session = null; 22 23 @Before 24 public void before(){ 25 //创建SqlSessionFactoryBuilder对象 26 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); 27 InputStream inputStream = null; 28 try { 29 //加载SqlMapConfig.xml配置文件 30 inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 //创建SqlSessionFactory对象 35 this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); 36 } 37 38 //修改用户 39 @org.junit.Test 40 public void updateUser(){ 41 //创建SqlSession对象 42 session = sqlSessionFactory.openSession(); 43 //创建需要修改的User对象 44 User user = new User(); 45 user.setId(31); 46 user.setUsername("神龙"); 47 user.setBirthday(new Date()); 48 user.setSex("1"); 49 user.setAddress("浦东"); 50 //执行修改操作 51 session.update("updateUser", user); 52 //提交事务 53 session.commit(); 54 } 55 56 @After 57 public void after(){ 58 //释放资源 59 session.close(); 60 } 61 }
3.3 执行结果:
四、删除用户
4.1 在 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 <!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 --> 6 <mapper namespace="user"> 7 <!-- id:statement的id 或者叫做sql的id--> 8 <!-- parameterType:声明输入参数的类型 --> 9 <!-- resultType:声明输出结果的类型,应该填写pojo的全路径 --> 10 <!-- #{}:输入参数的占位符,相当于jdbc的? --> 11 12 <!--根据id查询用户信息 --> 13 <select id="findUserById" parameterType="Integer" resultType="com.lwjnicole.pojo.User"> 14 select * from user where id = #{v} 15 </select> 16 17 <!--如果返回多个结果,mybatis会自动把返回的结果放在list容器中 --> 18 <!--resultType的配置和返回一个结果的配置一样 --> 19 <!--实现功能 :根据用户名模糊查询用户列表 --> 20 <select id="findUserByUsername" parameterType="String" resultType="com.lwjnicole.pojo.User"> 21 select * from user where username like '%${value}%' 22 </select> 23 24 <!--实现功能:新增用户 --> 25 <insert id="insertUser" parameterType="com.lwjnicole.pojo.User"> 26 <!--selectKey 标签实现主键返回 --> 27 <!--keyColumn :主键对应数据库表中的哪一列 --> 28 <!--keyProperty :主键对应pojo中的哪一个属性 --> 29 <!--order :设置在执行insert语句之前执行查询id的sql,还是在执行insert语句之后执行查询id的sql --> 30 <!--resultType:设置返回id的类型 --> 31 <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int"> 32 SELECT LAST_INSERT_ID() 33 </selectKey> 34 insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}); 35 </insert> 36 37 <!--实现功能:修改用户 --> 38 <update id="updateUser" parameterType="com.lwjnicole.pojo.User"> 39 update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} 40 </update> 41 42 <!--实现功能:删除用户 --> 43 <delete id="deleteUserById" parameterType="Integer"> 44 delete from user where id = #{id} 45 </delete> 46 </mapper>
4.2 Test类中新增Junit测试代码如下:
1 package mybatis_study; 2 3 import static org.junit.Assert.*; 4 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.util.Date; 8 import java.util.List; 9 10 import org.apache.ibatis.io.Resources; 11 import org.apache.ibatis.session.SqlSession; 12 import org.apache.ibatis.session.SqlSessionFactory; 13 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 14 import org.junit.After; 15 import org.junit.Before; 16 17 import com.lwjnicole.pojo.User; 18 19 public class Test { 20 private SqlSessionFactory sqlSessionFactory = null; 21 private SqlSession session = null; 22 23 @Before 24 public void before(){ 25 //创建SqlSessionFactoryBuilder对象 26 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); 27 InputStream inputStream = null; 28 try { 29 //加载SqlMapConfig.xml配置文件 30 inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 //创建SqlSessionFactory对象 35 this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); 36 } 37 38 //删除用户 39 @org.junit.Test 40 public void deleteUserById(){ 41 //创建SqlSession对象 42 session = sqlSessionFactory.openSession(); 43 //执行删除sql 44 session.delete("deleteUserById", 31); 45 //提交事务 46 session.commit(); 47 } 48 49 @After 50 public void after(){ 51 //释放资源 52 session.close(); 53 } 54 } 55
4.3 执行结果:
五、mybatis解决了JDBC的哪些问题
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 和 hibernate 的比较
Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。