mybatis教程--实现增删改查的入门教程
2017-04-21 10:26
525 查看
1 开发环境
jdk1.7.0_72eclipse:eclipse-3.7-indigo
mysql:mysql5.1
1.1 创建数据库
先导入sql_table.sql,再导入sql_data.sql(记录系统的初始化数据)
通常需要提供初始化数据的数据库脚本。
2 jdbc编程中问题
企业开发中,根据项目大小、特点进行技术选型,jdbc操作数据库时效率是很高的,jdbc也是技术选型的参考。
2.1 jdbc程序
需要数据库的驱动包:上边是mysql的驱动,下边是oracle的驱动。
2.2 jdbc问题总结
1、数据库连接频繁的创建和关闭,缺点浪费数据库的资源,影响操作效率设想:使用数据库连接池
2、sql语句是硬编码,如果需求变更需要修改sql,就需要修改java代码,需要重新编译,系统不易维护。
设想:将sql语句 统一配置在文件中,修改sql不需要修改java代码。
3、通过preparedStatement向占位符设置参数,存在硬编码( 参数位置,参数)问题。系统不易维护。
设想:将sql中的占位符及对应的参数类型配置在配置文件中,能够自动输入 映射。
4、遍历查询结果集存在硬编码(列名)。
设想:自动进行sql查询结果向java对象的映射(输出映射)。
3 mybatis架构
3.1 mybatis介绍
MyBatis 本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google
code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。 目前mybatis在github上托管。git(分布式版本控制,当前比较流程)
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL
本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
3.2 mybatis架构
4 mybatis入门程序
4.1 需求
实现用户查询:根据用户id(主键)查询用户信息(单条记录)
根据用户名称模糊查询用户信息(多条记录)
用户添加
用户删除
用户修改
4.2 导入jar包
从mybatis管网下载(地址:https://github.com/mybatis/mybatis-3/releases)
mybatis-3.2.7.pdf---操作手册
mybatis-3.2.7.jar--核心 jar包
依赖的jar包
4.3 工程结构
4.4 log4j.properties(公用文件)
# Global logging configuration,建议开发环境中要用debug log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
4.5 SqlMapConfig.xml(公用文件)
通过SqlMapConfig.xml加载mybatis运行环境。<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 属性定义 加载一个properties文件 在 properties标签 中配置属性值 --> <properties resource="db.properties"> <!-- <property name="" value=""/> --> </properties> <!-- 定义 别名 --> <typeAliases> <!-- 单个别名的定义 alias:别名,type:别名映射的类型 --> <!-- <typeAlias type="com.sihai.mybatis.po.User" alias="user"/> --> <!-- 批量别名定义 指定包路径,自动扫描包下边的pojo,定义别名,别名默认为类名(首字母小写或大写) --> <package name="com.sihai.mybatis.po"/> </typeAliases> <!-- 和spring整合后 environments配置将废除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理--> <transactionManager type="JDBC" /> <!-- 数据库连接池--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!--加载mapper映射 如果将和spring整合后,可以使用整合包中提供的mapper扫描器,此处的mappers不用配置了。 --> <mappers> <!-- 通过resource引用mapper的映射文件 --> <mapper resource="sqlmap/User.xml" /> <!-- <mapper resource="mapper/UserMapper.xml" /> --> <!-- 通过class引用mapper接口 class:配置mapper接口全限定名 要求:需要mapper.xml和mapper.java同名并且在一个目录 中 --> <!-- <mapper class="com.sihai.mybatis.mapper.UserMapper"/> --> <!-- 批量mapper配置 通过package进行自动扫描包下边的mapper接口, 要求:需要mapper.xml和mapper.java同名并且在一个目录 中 --> <package name="com.sihai.mybatis.mapper"/> </mappers> </configuration>
4.6 实现用户增删改查
4.6.1 pojo(User.java)
package com.sihait.mybatis.po; import java.util.Date; /** * @author sihai */ public class User { private int id; private String username;// 用户姓名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + "]"; } }
4.6.2 User.xml(重点)
建议命名规则:表名+mapper.xml早期ibatis命名规则:表名.xml
<?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"> <!-- namespace命名空间,为了对sql语句进行隔离,方便管理 ,mapper开发dao方式,使用namespace有特殊作用 mapper代理开发时将namespace指定为mapper接口的全限定名 --> <mapper namespace="test"> <!-- 在mapper.xml文件中配置很多的sql语句,执行每个sql语句时,封装为MappedStatement对象 mapper.xml以statement为单位管理sql语句 --> <!-- 根据id查询用户信息 --> <!-- id:唯一标识 一个statement #{}:表示 一个占位符,如果#{}中传入简单类型的参数,#{}中的名称随意 parameterType:输入 参数的类型,通过#{}接收parameterType输入 的参数 resultType:输出结果 类型,不管返回是多条还是单条,指定单条记录映射的pojo类型 --> <select id="findUserById" parameterType="int" resultType="com.sihai.mybatis.po.User"> SELECT * FROM USER WHERE id= #{id} </select> <!-- 根据用户名称查询用户信息,可能返回多条 ${}:表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中。 --> <select id="findUserByName" parameterType="java.lang.String" resultType="com.sihai.mybatis.po.User"> select * from user where username like '%${value}%' </select> <!-- 添加用户 parameterType:输入 参数的类型,User对象 包括 username,birthday,sex,address #{}接收pojo数据,可以使用OGNL解析出pojo的属性值 #{username}表示从parameterType中获取pojo的属性值 selectKey:用于进行主键返回,定义了获取主键值的sql order:设置selectKey中sql执行的顺序,相对于insert语句来说 keyProperty:将主键值设置到哪个属性 resultType:select LAST_INSERT_ID()的结果 类型 --> <insert id="insertUser" parameterType="com.sihai.mybatis.po.User"> <selectKey keyProperty="id" order="AFTER" resultType="int"> select LAST_INSERT_ID() </selectKey> INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address}) </insert> <!-- mysql的uuid生成主键 --> <!-- <insert id="insertUser" parameterType="com.sihai.mybatis.po.User"> <selectKey keyProperty="id" order="BEFORE" resultType="string"> select uuid() </selectKey> INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address}) </insert> --> <!-- oracle 在执行insert之前执行select 序列.nextval() from dual取出序列最大值,将值设置到user对象 的id属性 --> <!-- <insert id="insertUser" parameterType="com.sihai.mybatis.po.User"> <selectKey keyProperty="id" order="BEFORE" resultType="int"> select 序列.nextval() from dual </selectKey> INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address}) </insert> --> <!-- 用户删除 --> <delete id="deleteUser" parameterType="int"> delete from user where id=#{id} </delete> <!-- 用户更新 要求:传入的user对象中包括 id属性值 --> <update id="updateUser" parameterType="com.sihai.mybatis.po.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper>
4.6.3 测试
创建SqlSessionFactory:
package com.sihai.mybatis.first; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.sihai.mybatis.po.User; /** * @author sihai */ public class MybatisFirst { // 会话工厂 private SqlSessionFactory sqlSessionFactory; // 创建工厂 @Before public void init() throws IOException { // 配置文件(SqlMapConfig.xml) String resource = "SqlMapConfig.xml"; // 加载配置文件到输入 流 InputStream inputStream = Resources.getResourceAsStream(resource); // 创建会话工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } // 测试根据id查询用户(得到单条记录) @Test public void testFindUserById() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库 // 第一个参数:statement的位置,等于namespace+statement的id // 第二个参数:传入的参数 User user = null; try { user = sqlSession.selectOne("test.findUserById", 2); } catch (Exception e) { e.printStackTrace(); } finally { // 关闭sqlSession sqlSession.close(); } System.out.println(user); } // 测试根据id查询用户(得到单条记录) @Test public void testFindUserByName() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库 // 第一个参数:statement的位置,等于namespace+statement的id // 第二个参数:传入的参数 List<User> list = null; try { list = sqlSession.selectList("test.findUserByName", "小明"); } catch (Exception e) { e.printStackTrace(); } finally { // 关闭sqlSession sqlSession.close(); } System.out.println(list.get(0).getUsername()); } // 测试根据id查询用户(得到单条记录) @Test public void testInsertUser() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库 // 创建插入数据对象 User user = new User(); user.setUsername("浪子燕青"); user.setAddress("河南郑州"); user.setBirthday(new Date()); user.setSex("1"); try { sqlSession.insert("test.insertUser", user); // 需要提交事务 sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } finally { // 关闭sqlSession sqlSession.close(); } System.out.println("用户的id=" + user.getId()); } // 测试根据id删除用户(得到单条记录) @Test public void testDeleteUser() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库 try { sqlSession.delete("test.deleteUser", 35); // 需要提交事务 sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } finally { // 关闭sqlSession sqlSession.close(); } } // 测试根据id更新用户(得到单条记录) @Test public void testUpdateUser() { // 通过sqlSessionFactory创建sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通过sqlSession操作数据库 // 创建更新数据对象,要求必须包括 id User user = new User(); user.setId(35); user.setUsername("燕青"); user.setAddress("河南郑州"); // user.setBirthday(new Date()); user.setSex("1"); try { sqlSession.update("test.updateUser", user); // 需要提交事务 sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } finally { // 关闭sqlSession sqlSession.close(); } System.out.println("用户的id=" + user.getId()); } }
5 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定义输出结果的类型。
6 mybatis与hibernate重要区别
企业开发进行技术选型 ,考虑mybatis与hibernate适用场景。mybatis:入门简单,程序容易上手开发,节省开发成本 。mybatis需要程序员自己编写sql语句,是一个不完全 的ORM框架,对sql修改和优化非常容易实现
。
mybatis适合开发需求变更频繁的系统,比如:互联网项目。
hibernate:入门门槛高,如果用hibernate写出高性能的程序不容易实现。hibernate不用写sql语句,是一个ORM框架。
hibernate适合需求固定,对象数据模型稳定,中小型项目,比如:企业OA系统。
总之,企业在技术选型时根据项目实际情况,以降低成本和提高系统
可维护性为出发点进行技术选型。
7 总结
7.1 #{}
表示一个占位符,向占位符输入参数,mybatis自动进行java类型和jdbc类型的转换。程序员不需要考虑参数的类型,比如:传入字符串,mybatis最终拼接好的sql就是参数两边加单引号。
#{}接收pojo数据,可以使用OGNL解析出pojo的属性值
7.2 ${}
表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中。${}也可以接收pojo数据,可以使用OGNL解析出pojo的属性值
缺点:不能防止sql注入。
相关文章推荐
- MyBatis系列教程(三)--实现数据的增删改查(CRUD)
- mybatis实战教程(mybatis in action)之三:实现数据的增删改查(转)
- SSM搭建-Mybatis入门概述及第一个Mybatis实例实现增删改查(16)
- JAVAWEB开发之mybatis详解(一)——mybatis的入门(实现增删改查操作)、自定义别名、抽取代码块以及动态SQL的使用
- 19、SSM框架-Mybatis入门概述及第一个Mybatis实例实现增删改查(1)
- JAVAWEB开发之mybatis详解(一)——mybatis的入门(实现增删改查操作)、自定义别名、抽取代码块以及动态SQL的使用
- 快速入门GreenDao框架并实现增删改查案例
- mybatis实战教程(mybatis in action)之三:实现数据的增删改查
- mybatis实现的增删改查例子
- Spring mvc整合mybatis基于mysql数据库实现用户增删改查及其分页显示的完整入门实例【转】
- Mybatis实现增删改查(CRUD)实例代码
- Mybatis实现数据的增删改查(CRUD)
- Mybatis入门概述及第一个Mybatis实例实现增删改查
- ztree使用系列三(ztree与springmvc+spring+mybatis整合实现增删改查)
- Spring mvc整合mybatis基于mysql数据库实现用户增删改查及其分页显示的完整入门实例【转】
- Spring mvc整合mybatis基于mysql数据库实现用户增删改查及其分页显示的完整入门实例【转】
- Mybatis实现数据的增删改查(CRUD)
- MyBatis入门教程(二):实现CRUD
- MyBatis实战教程之四增删改查操作
- 使用MyBatis对表执行增删改查操作——基于注解的实现