Mybatis
Posted miantiao312
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis相关的知识,希望对你有一定的参考价值。
Dao开发方法
使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法。
先介绍几个概念
a、SqlSession的使用范围
SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。
通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建
b、SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不
需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可
以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
c、SqlSessionFactory
SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory
的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
d、SqlSession
SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作方法。每个线程都应该有它自己的
SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法
范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。打开一个 SqlSession,
使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭
1、原始Dao开发方式:原始Dao开发方法需要程序员编写Dao接口和Dao实现类。
需求:根据用户id查询一个用户信息
根据用户名称模糊查询用户信息列表
添加用户信息
Dao接口和实现
接口
public interface UserDao {
User getUserById(int id);
List<User> getUserByUsername(String username);
void insertUser(User user);
}
实现
public class UserDaoImpl implements UserDao {
//注入SqlSessionFactory
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User getUserById(int id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 根据id查询用户信息
User user = sqlSession.selectOne("getUserById", id);
// 关闭SQLSession
sqlSession.close();
return user;
}
@Override
public List<User> getUserByUsername(String username) {
// 创建一个SQLSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行查询
List<User> list = sqlSession.selectList("getUserByUsername", username);
// 释放资源
sqlSession.close();
return list;
}
@Override
public void insertUser(User user) {
// 创建一个SQLSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 插入用户
sqlSession.insert("insertUser", user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
测试
public class UserDaoImplTest {
//创建会话工厂
private SqlSessionFactory sqlSessionFactory = null;
@Before
public void createSqlSessionFactory() throws Exception {
//第一步:创建一个SQLSessionFactoryBuilder对象。
SqlSessionFactoryBuilder sessionFactoryBuilder=new SqlSessionFactoryBuilder();
//第二步:加载配置文件。
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//第三步:创建SQLSessionFactory对象
sqlSessionFactory = sessionFactoryBuilder.build(inputStream);
}
@Test //根据用户id获取用户
public void getUserByIdTest() {
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
User user = userDao.getUserById(10);
System.out.println(user);
}
@Test //通过用户名查询用户
public void findUserByUsernameTest() {
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
List<User> list = userDao.getUserByUsername("张");
for (User user : list) {
System.out.println(user);
}
}
@Test
public void insertUserTest() {
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
User user = new User();
user.setUsername("赵云");
user.setAddress("正定");
user.setBirthday(new Date());
user.setSex("1");
userDao.insertUser(user);
}
}
原始Dao开发中存在以下问题:
Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作
方法调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护。
2、Mapper动态代理方式
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义
创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
a、Mapper.xml文件中的namespace与mapper接口的类路径相同。
b、Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
c、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
d、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
创建包 com.kid.mybatis.mapper
a、接口:UserMapper
public interface UserMapper {
User getUserById(int id);
List<User> getUserByUsername(String username);
void insertUser(User user);
}
b、映射文件:UserMapper.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语句的隔离,
#{}作用就是占位符,相当于jdbc的“?”
parameterType:查询的参数类型
定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。
resultType:查询结果的数据类型,如果是pojo应该给全路径。
-->
<!-- mapper代理的开发规则:
1、namespace必须时候接口的全限定名
2、Statementid必须和接口的方法名称一致
3、接口方法的参数类型要和parameterType要一致
4、接口方法的返回值类型要和resultType一致
-->
<mapper namespace="com.kid.mybatis.mapper.UserMapper">
<!-- 通过用户id获取用户 -->
<select id="getUserById" parameterType="int" resultType="user">
select * from user where id = #{id}
</select>
<!-- 如果查询结果返回list, resultType设置为list中一个元素的数据类型
${}字符串拼接指令
-->
<select id="getUserByUsername" parameterType="string" resultType="user">
<!-- ${value}表示使用参数将${value}替换,做字符串的拼接。
注意:如果是取简单数量类型的参数,括号中的值必须为value
-->
select * from user where username like ‘%${value}%‘
</select>
<!-- 参数时候pojo时,#{}中的名称就是pojo的属性 -->
<insert id="insertUser" parameterType="user">
<!-- keyProperty:对于pojo的主键属性
resultType:对应主键的数据类型
order:是在insert语句执行之前或者之后。
如果使用uuid做主键,应该先生成主键然后插入数据,此时应该使用Before
-->
<selectKey keyProperty="id" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address)
value(#{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
c、改造SqlMapperConfig.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>
<!-- 配置属性 先加载内部属性,再加载外部属性,如果有同名属性会覆盖-->
<properties resource="db.properties"/>
<!-- 配置pojo别名 -->
<typeAliases>
<!-- 扫描包的形式创建别名,别名就是类名,不区分大小写 -->
<package name="com.kid.mybatis.pojo"/>
</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文件 -->
<mappers>
<!-- resource基于classpath查找 -->
<mapper resource="sqlmap/user.xml"/>
<!-- 根据接口名称加载mapper文件
要求:1、mapper映射文件和接口在同一个目录下
2、mapper映射文件的名称和接口名称一致。
3、class就是接口的权限定名
-->
<!-- 使用扫描包的形式加载mapper文件 -->
<package name="com.kid.mybatis.mapper"/>
</mappers>
</configuration>
测试用例
public class UserMapperTest {
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 //根据用户id获取用户
public void getUserByIdTest() {
//和spring整合后省略
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(10);
System.out.println(user);
//和spring整合后省略
sqlSession.close();
}
@Test //通过用户名查询用户
public void findUserByUsernameTest() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.getUserByUsername("张");
for (User user : list) {
System.out.println(user);
}
sqlSession.close();
}
@Test
public void insertUserTest() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("关羽");
user.setAddress("硅谷");
user.setBirthday(new Date());
user.setSex("2");
userMapper.insertUser(user);
sqlSession.commit();
sqlSession.close();
}
}
以上是关于Mybatis的主要内容,如果未能解决你的问题,请参考以下文章
SSM-MyBatis-05:Mybatis中别名,sql片段和模糊查询加getMapper
MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段