写在前面,mybatis是一款优秀的开源框架,学习任何一个新的框架之前,先搭建起环境
mybatis运行环境(jar包):
从https://github.com/mybatis/mybatis-3/releases下载,3.2.7版本
lib下:依赖包
mybatis-3.2.7.jar:核心 包
mybatis-3.2.7.pdf,操作指南
第一步:创建java工程
使用eclipse创建java工程,jdk使用1.8.0_65。
第二步:加入jar包
加入mybatis核心包、依赖包、数据驱动包
第三步:log4j.properties
在classpath下创建log4j.properties如下:
# Global logging configuration
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
mybatis默认使用log4j作为输出日志信息
第四步:SqlMapConfig.xml
在classpath下创建SqlMapConfig.xml,如下:
<?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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="admin" />
</dataSource>
</environment>
</environments>
</configuration>
SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。
第五步:po类
Po类作为mybatis进行sql映射使用,po类通常与数据库表对应,User.java如下:
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 + "]";
}
}
第六步:程序编写查询
6.1 映射文件:
在classpath下的sqlmap目录下创建sql映射文件Users.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进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用
-->
<mapper namespace="test">
</mapper>
namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。
6.2 在User.xml中添加:
<!-- 根据id获取用户信息 -->
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
select * from user where id = #{id}
</select>
<!-- 自定义条件查询用户列表 -->
<select id="findUserByUsername" parameterType="java.lang.String"
resultType="cn.itcast.mybatis.po.User">
select * from user where username like '%${value}%'
</select>
parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。resultType:定义结果映射类型。
6.3 加载映射文件
mybatis框架需要加载映射文件,将Users.xml添加在SqlMapConfig.xml,如下:
<?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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="admin" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载 映射文件 -->
<mapper resource="sqlmap/Users.xml"/>
</mappers>
</configuration>
6.4 工程大体结构:
6.5 测试程序:
public class MybatisFirst {
// 根据id查询用户信息,得到一条记录结果
@Test
public void findUserById() throws Exception {
// mybatis配置文件
String resource="SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream=Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
// 通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
User user=sqlSession.selectOne("test.findUserById", 1);
System.out.println(user);
}
// 根据用户名称模糊查询用户列表
@Test
public void findUserByNameTest() throws Exception {
// mybatis配置文件
String resource="SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream=Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
// 通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession.selectList("test.findUserByName", "王");
System.out.println(list);
}
这里有一个需要注意的地方,就是sqlSession.selectOne("test.findUserById", 1)里面的findUserById前面的名字要与SQL映射文件的mapper namespace=“test” 名字相对应,不然会无法加载文件
二、总结:
2.1 parameterType
在映射文件中通过parameterType指定输入 参数的类型。
2.2 resultType
在映射文件中通过resultType指定输出结果的类型。
2.3 #{}和${}
#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称。
#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
${}表示一个拼接符号,会引用sql注入,所以不建议使用${}。
在这里稍微解释一下,什么叫做sql注入
首先来看一下下面这样一个SQL语句:
"select username,password from user where username = '"+username+"'and password = '"+password+"'"
此SQL语句是根据用户名和密码来从数据库中获取记录,有用户名和密码作为双重验证。如果此时没有对用户输入的username加以判断和字符过滤,将username输入成如下字符:
admin‘ #
那么此时拼接后的完整SQL语句将变为如下形式:
"select username,password from user where username = 'admin' #'and password = '123456'"
我们知道,在MySQL中,#是注释的意思,这样对password的限制就彻底失效了,只要数据库中有admin这条记录,数据库就会有数据返回。这样就背离了我们想要执行目标SQL语句的初衷。这就是典型的SQL注入。
${}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,${}中只能写成value。
${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
2.4 selectOne和selectList
selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。
selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne。
如果使用selectOne报错:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4
2.5 何时提交事务
在做添加、删除和修改功能时需要提交事务,在查询时不需要提交事务的
// 更新用户信息
@Test
public void updateUserTest() throws Exception {
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 插入用户对象
User user = new User();
//必须设置id
user.setId(26);
user.setUsername("林东");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("西安");
sqlSession.update("test.updateUser", user);
// 提交事务
sqlSession.commit();
// 获取用户信息主键
System.out.println(user.getAddress());
// 关闭会话
sqlSession.close();
}
三、properties属性
需求:
将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值。
在SqlMapConfig.xml中就不需要对数据库连接参数硬编码。
将数据库连接参数只配置在db.properties中,原因:方便对参数进行统一管理,其它xml可以引用该db.properties。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=admin
在sqlMapConfig.xml加载属性文件:
四、typeAliases(别名)重点
需求
在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。
如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发
4.1 单个别名定义:
引用别名:
4.2 批量别名定义(常用)
五、 通过mapper接口加载单个mapper
按照上边的规范,将mapper.java和mapper.xml放在一个目录 ,且同名
批量加载mapper(推荐使用)