MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc复杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由Mybatis框架执行sql并将结果映射成java对象并返回。
MyBatis架构
配置MyBatis
在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="123" />
</dataSource>
</environment>
</environments>
</configuration>
在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">
<mapper namespace="test">
</mapper>
namespace:命名空间,用于隔离sql语句。
1.必须是接口的全限定名
2.Statementid必须和接口的方法名称一致
3.接口方法的参数类型要和parameterType要一致
4.接口方法的返回值类型要和resultType一致
映射文件:
<!-- 根据id获取用户信息 -->
<select id="findUserById" parameterType="int" resultType="com.baidu.mybatis.po.User">
select * from user where id = #{id}
</select>
#{}作用就是占位符,相当于jdbc的“?”;
parameterType:查询的参数类型。
resultType:查询结果的数据类型,如果是pojo应该给全路径
mybatis框架需要加载映射文件,将Users.xml添加在SqlMapConfig.xml
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mappers>
private SqlSessionFactory sqlSessionFactory=null;
@Before
public void init() throws Exception{
//第一步:创建一个SQLSessionFactoryBuilder对象。
SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
//第二部:加载配置文件
InputStream inputStream=Resources.getResourceAsStream("SqlMapConfig.xml");
//第三步:创建SQLSessionFactory对象
sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
}
@Test
public void getUserById() throws Exception {
// 第四步:创建SQLSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 第五步:使用SQLSession对象执行查询,得到User
// 第一个参数:执行查询statementId
User user = sqlSession.selectOne("getUserById", 10);
// 第六步:打印结果
System.out.println(user);
// 第七步:释放资源
sqlSession.close();
}
根据用户名查询用户信息
在user.xml中添加
<!-- 如果查询结果返回list。resultType设置为list中一个元素对的数据类型
${}字符串拼接指令
-->
<select id="getUserByName" parameterType="string" resultType="java.lang.String">
SELECT * FROM USER WHERE username LIKE '%${value}%';
</select>
parameterType:定义输入到sql中的映射类型,
v
a
l
u
e
表
示
使
用
参
数
将
{value}表示使用参数将
value表示使用参数将{value}替换,做字符串的拼接。
注意:如果是取简单数量类型的参数,括号中的值必须为value
resultType:定义结果映射类型。
代码测试
@Test
public void getUserByName()throws Exception{
//创建一个SQLSession对象
SqlSession session = sqlSessionFactory.openSession();
//执行查询
List<User>list=session.selectList("getUserByName","%张%");
for (User user : list) {
System.out.println(user);
}
//释放资源
session.close();
}
#{}和$ {}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符设置,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值。如果parameterType传输单个类型值,#{}括号中可以是value或其它名称。
$ {}表示拼接sql串,通过$ {}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,$ {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,$ {}括号中只能是value
parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象
selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常
selectList可以查询一条或多条记录。
添加用户
在SqlMapConfig.xml中添加
<insert id="insertUser" parameterType="com.baidu.mybatis.po.User">
<!-- selectKey将主键返回,需要再返回 -->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address});
</insert>
添加selectKey实现将主键返回
keyProperty:返回的主键存储在pojo中的哪个属性
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after
resultType:返回的主键是什么类型
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
@Test
public void addUser()throws Exception{
//创建一个SQLSession对象
SqlSession session = sqlSessionFactory.openSession();
//创建User对象
User user=new User();
user.setUsername("赵四");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("北京");
session.insert("insertUser",user);
//提交
session.commit();
session.close();
}
删除用户
映射文件
<!-- 删除用户 -->
<delete id="deleteUserById" parameterType="int">
delete from user where id=#{id}
</delete>
@Test
public void deleteUser()throws Exception{
SqlSession session = sqlSessionFactory.openSession();
session.delete("deleteUser",27);
session.commit();
session.close();
}
修改用户
<!-- 修改用户 -->
<update id="updateUser" parameterType="com.baidu.mybatis.po.User">
update user set username=#{username} where id=#{id}
</update>
@Test
public void updateUser()throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
User user=new User();
user.setUsername("王六");
user.setId(26);
sqlSession.update("updateUser",user);
sqlSession.commit();
sqlSession.close();
}
一.SqlSession的使用范围
SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。
通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
(1).SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory产生,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
(2).SqlSessionFactory
SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory.
(3).6.2.3 SqlSession
SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作方法。
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
SqlMapConfig.xml配置文件
1.配置内容
SqlMapConfig.xml中配置的内容和顺序:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
evironments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
2.properties(属性)
SqlMapConfig.xml可以引用java属性文件中的配置信息
在classpath下定义db.properties文件,
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
SqlMapConfig.xml
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<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>
注意: MyBatis 将按照下面的顺序来加载属性:
(1): 在 properties 元素体内定义的属性首先被读取。
(2): 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
3.自定义别名
简单用法
4.7.4.3 < package name=""/>
< mappers>
基于classPath查询
根据接口名称加载mapper文件
要求:1.mapper映射文件和接口在同一个目录下
2.mapper映射文件的名称和接口名称一致
3.class就是接口的权限定名
< /mappers>