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对象并返回。
Mybatis官方文档:http://www.mybatis.org/mybatis-3/zh/index.html
JDBC存在问题总结
- 数据库连接频繁的创建和关闭,缺点浪费数据库的资源,影响操作效率
设想:使用数据库连接池 - sql语句是硬编码,如果需求变更需要修改sql,就需要修改java代码,需要重新编译,系统不易维护。
设想:将sql语句 统一配置在文件中,修改sql不需要修改java代码。 - 通过preparedStatement向占位符设置参数,存在硬编码( 参数位置,参数)问题。系统不易维护。
设想:将sql中的占位符及对应的参数类型配置在配置文件中,能够自动输入 映射。 - 遍历查询结果集存在硬编码(列名)。
设想:自动进行sql查询结果向java对象的映射(输出映射)。
MyBatis架构
MyBatis入门程序
1 导入jar包
mybatis-3.2.7.jar–核心 jar包
依赖包
2 SqlMapConfig.xml
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 属性定义
1、使用resource加载一个properties文件
2、在properties标签中配置属性值
-->
<properties resource="db.properties">
<!-- <property name="" value=""/> -->
</properties>
<!-- 和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>
<mapper resource="sqlmap/User.xml" />
</mappers>
</configuration>
3 User.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">
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE id= #{id}
</select>
<select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
select * from user where username like '%${value}%'
</select>
<insert id="insertUser" parameterType="cn.itcast.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>
<!-- 用户删除 -->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
</mapper>
4 实体类
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 + "]";
}
}
5 测试程序:
public class MybatisFirst {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
String resource = "SqlMapConfig.xml";
// MyBatis 提供Resources读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() {
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);
}
@Test
public void testFindUserByName() {
SqlSession sqlSession = sqlSessionFactory.openSession();
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());
}
@Test
public void testInsertUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
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.close();
}
System.out.println("用户的id=" + user.getId());
}
// 测试根据id删除用户(得到单条记录)
@Test
public void testDeleteUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
sqlSession.delete("test.deleteUser", 31);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
@Test
public void testUpdateUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(27);
user.setUsername("燕青");
user.setAddress("河南郑州");
user.setSex("1");
try {
sqlSession.update("test.updateUser", user);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
System.out.println("用户的id=" + user.getId());
}
}
mybatis入门程序开发小结
- 编写SqlMapConfig.xml
- 编写mapper.xml
定义了statement - 编程通过配置文件创建SqlSessionFactory
- 通过SqlSessionFactory获取SqlSession
- 通过SqlSession操作数据库
如果执行添加、更新、删除需要调用SqlSession.commit() - SqlSesion使用完成要关闭
各配置文件介绍
SqlMapConfig.xml
MyBatis全局配置文件,只有一个,名称不固定。
配置项说明
- properties——属性
- settings——全局配置参数
- typeAliases——类型别名
- typeHandlers——类型处理器
- objectFactory——对象工厂
- plugins——插件
- environments——环境集合属性对象
- environment——环境子属性对象
- transactionManager——事务管理
- dataSource——数据源
- mappers——映射器
说明具体配置说明见代码注释。
properties属性定义
可以把一些通用的属性值配置在属性文件中,加载到mybatis运行环境内。
注意: MyBatis 将按照下面的顺序来加载属性:
- 在 properties 元素体内定义的属性首先被读取。
- 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
- 最后读取parameterType传递的属性,它会覆盖已读取的同名属性。
建议使用properties,不要在properties中定义属性,只引用定义的properties文件中属性,并且properties文件中定义的key要有一些特殊的规则。
settings全局参数配置
mybatis运行时可以调整一些全局参数(相当于软件的运行参数)
根据使用需求进行参数配置。
注意:小心配置,配置参数会影响mybatis的执行。
ibatis的全局配置参数中包括很多的性能参数(最大线程数,最大待时间。。。),通过调整这些性能参数使ibatis达到高性能的运行,mybatis没有这些性能参数,由mybatis自动调节。
mapper.xml
mapper.xml是以statement为单位进行配置。(把一个sql称为一个statement)。
satatement中配置 sql语句、parameterType输入参数类型(完成输入映射)、resultType输出结果类型(完成输出映射)。
还提供了parameterMap配置输入参数类型(过期了,不推荐使用了)
还提供resultMap配置输出结果类型(完成输出映射)。
mapper.xml常用属性说明
namespace命名空间
为了对sql语句进行隔离,方便管理 ,mapper开发dao方式,使用namespace有特殊作用
mapper代理开发时将namespace指定为mapper接口的全限定名
两种占位符
- #{}
表示一个占位符,向占位符输入参数,mybatis自动进行java类型和jdbc类型的转换。
程序员不需要考虑参数的类型,比如:传入字符串,mybatis最终拼接好的sql就是参数两边加单引号。
接收pojo数据,可以使用OGNL解析出pojo的属性值 -
表示sql的拼接,通过
{}接收参数,将参数的内容不加任何修饰拼接在sql中。
${}也可以接收pojo数据,可以使用OGNL解析出pojo的属性值
缺点:不能防止sql注入。