首先, 回顾Mybatis的入门使用方法:
- 创建Java工程
-
导入相关jar包
jar.png
其中, 需要数据库驱动包, Mybatis核心包, 包括JUnit单元测试所需的jar包 hamcrest-core
和junit-4.12
日志格式输出的jar包 log4j
和commons-logging
- 准备Mybatis的全局配置文件
具体内容见上一篇整理的博客! - 准备Mybatis的映射文件
在映射文件中编写sql语句
单元测试程序:
SqlSession对象的获取和使用:
SqlSessionFactoryBuilder ---> SqlSessionFactory ---> SqlSession
SqlSessionFactoryBuilder : build(InputStream in) 获取SqlSessionFactory
SqlSessionFactory : openSession() 获取SqlSession
SqlSession:
selectOne(String id , Object param);
selectList(String id ,Object param);
insert()
delete()
update()
CRUD
增加
添加用户信息
这里提供了操作的实体类User.java
:
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// getter and setter, toString() 省略
}
select last_insert_id()
insert into `user` values(#{id}, #{username}, #{birthday}, #{sex}, #{address})
单元测试代码:
@Test
public void insertUser() throws Exception {
// 得到全局配置文件的输入流对象
InputStream in = Resources.getResourceAsStream("mybatis/sqlMapConfig.xml");
// 得到Session工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 得到SqlSession
SqlSession session = factory.openSession();
// 创建User对象
User user = new User();
user.setUsername("小阳");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("湖北武汉");
// 调用的是session的insert()方法
/*
还传入的参数是一个User对象
如果是增删改, 一定要记得提交事务
*/
session.insert("demo.insertUser", user);
System.out.println(user);
session.commit();
// 关闭session
session.close();
}
查询
分多种查询
这里的单元测试略, 和上面类似.
改
映射文件:
update `user` set username = #{username}, birthday=#{birthday}, sex=#{sex}, address=#{address} where id=#{id}
删除
相关映射文件:
delete from user where id = #{abc}
注意事项:
// 如果查询结果集中有多条记录, 那么使用selectList(String id, Object param)
/*
如果这时使用selectOne, 那么这时会抛出
org.apache.ibatis.exceptions.TooManyResultsException:
Expected one result (or null) to be returned by selectOne(), but found: 3
异常
*/
映射文件SQL语句书写小结
parameterType
: 输入参数类型, 一定是类型的全名, 或者是别名(int)
resultType
: 输出参数类型
#{}
: 占位符, 如果是简单类型, 那么里面可以随便写
${}
: 是连接符, 如果是简单类型, 那么里面只能是value
如果parameterType
是自定义类的类型, 那么#{}, ${}里面都要写该类型的属性名
Mybatis开发Dao层
SqlSession对象: 该对象是线程不安全的, 所以不能定义为成员变量, 只能定义局部变量.
SqlSessionFactory: 该对象在项目中只需要一个, 那么该变量可以定义为成员变量
Dao 接口
Dao的实现类:
public class UserDaoImpl implements UserDao {
private SqlSessionFactory factory;
public UserDaoImpl(SqlSessionFactory factory) {
this.factory = factory;
}
@Override
public void addUser(User user) throws Exception {
SqlSession session = factory.openSession();
session.insert("demo.insertUser", user);
session.commit();
session.close();
}
@Override
public void deleteUser(Integer id) throws Exception {
SqlSession session = factory.openSession();
session.delete("demo.deleteById", id);
session.commit();
session.close();
}
@Override
public void updateUser(User user) throws Exception {
SqlSession session = factory.openSession();
session.update("demo.updateUser", user);
session.commit();
session.close();
}
@Override
public User findUserById(Integer id) throws Exception {
// 获取SqlSession对象
SqlSession session = factory.openSession();
User user = session.selectOne("demo.findUserById", id);
return user;
}
@Override
public List findAllUser() throws Exception {
SqlSession session = factory.openSession();
List userList = session.selectList("demo.findAllUser");
return userList;
}
}
测试类:
public class UserDaoImplTest {
private SqlSessionFactory factory;
// 用来获取工厂
@Before
public void getFactory() throws Exception {
this.factory = new SqlSessionFactoryBuilder().
build(Resources.getResourceAsStream("mybatis/sqlMapConfig.xml"));
}
@Test
public void testFindUser() throws Exception {
// 获取UserDao对象
UserDao userDao = new UserDaoImpl(factory);
User user = userDao.findUserById(28);
System.out.println(user);
}
@Test
public void testFindAllUser() throws Exception {
// 获取UserDao对象
UserDao userDao = new UserDaoImpl(factory);
List userList = userDao.findAllUser();
System.out.println(userList);
}
@Test
public void testAddUser() throws Exception {
// 获取UserDao对象
UserDao userDao = new UserDaoImpl(factory);
User user = new User();
user.setUsername("小花");
user.setSex("2");
user.setBirthday(new Date());
user.setAddress("武汉");
userDao.addUser(user);
System.out.println(user);
}
@Test
public void deleteUser() throws Exception {
// 获取UserDao对象
UserDao userDao = new UserDaoImpl(factory);
userDao.deleteUser(29);
}
@Test
public void updateUser() throws Exception {
// 获取UserDao对象
UserDao userDao = new UserDaoImpl(factory);
User user = new User();
user.setId(28);
user.setUsername("小阳");
user.setSex("2");
user.setBirthday(new Date());
user.setAddress("武汉");
userDao.updateUser(user);
System.out.println(user);
}
}
Mapper代理模式开发DAO
上面的dao传统开发模式有两个不太好的地方:
- 我们需要在每个dao方法中去获取SqlSession对象, 并且调用SqlSession中的方法, 在每个方法中都是差不多的.
- 在每次调用SqlSession方法的时候, 传入的第一个参数都是硬编码, 写死了, 不好!!!
由此, 我们引入Mapper代理模式开发dao层
因为在每个dao的实现类的方法中, 存在大量的模板代码, 那么这些代码, 可以通过一个代理对象来调用. 但是这个代理对象根据dao的接口来生成, 所以在Mapper代理开发中, 我只需要编写dao的接口, 不需要编写其实现类.
1. 准备映射文件
如果采用的mapper代理开发模式, 那么映射文件的命名空间必须是
Mapper接口的全路径
2. 编写接口中的方法
三个特点:
1. Mapper接口中的方法名必须和映射文件中的sql语句的id一致
2. Mapper接口中的方法的返回值类型必须和resultType一致, 如果返回的
结果有多条记录, 那么返回值是List, 但是元素类型和resultType一致
3. Mapper接口中的方法参数必须和映射文件中parameterType一致
见代码:
/**
* mapper开发的接口
* Created by menglanyingfei
* on 2018/1/20.
*/
public interface UserMapper {
List findUserByName(String name);
}
测试代码:
public class MapperTest {
private SqlSessionFactory factory;
@Before
public void getFactory() throws Exception {
this.factory = new SqlSessionFactoryBuilder().
build(Resources.getResourceAsStream("mybatis/sqlMapConfig.xml"));
}
@Test
public void testFindUserByName() {
// 获取SqlSession
SqlSession session = factory.openSession();
// 通过SqlSession对象得到Mapper接口的一个代理对象
// 需要传递的参数是Mapper接口的类型
UserMapper userMapper = session.getMapper(UserMapper.class);
// 通过代理对象调用UserMapper中的方法
List userList = userMapper.findUserByName("小");
System.out.println(userList);
// 红色标识!
System.err.println(userMapper);
// org.apache.ibatis.binding.MapperProxy@289d1c02
// 关闭资源
session.close();
}
Mybatis全局配置文件的一些配置信息
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
-- environment(环境子属性对象)
---- transactionManager(事务管理)
---- dataSource(数据源)
mappers(映射器)
注意:上面几项配置, 必须按照顺序进行配置
settings(全局配置参数)
该配置中可以配置全局参数, 比如二级缓存, 延迟加载和日志信息的配置
配置信息参考: mybatis-settings.xlsx(包含在下面的代码文件夹中)
properties: 一般用来配置数据库的连接信息
在properties标签体, 还可以通过property标签来设置属性, 但是此时的加载顺序是先加载的是property标签中的属性, 然后再加载resource指定的外部属性文件中的属性.
typeAliases(类型别名, 重要)
Mybatis默认支持的别名
自定义别名:
-
配置单个别名:
image.png -
批量配置别名: mybatis扫描某一个包, 对包下的所有类都创建别名
image.png
typeHandlers(类型处理器)
一般不需要配置
补充(但使用较少!):
mappers(映射器)
用来在全局配置文件中加载映射文件
加载单个映射文件
完!
完整代码地址见:
https://github.com/menglanyingfei/SSMLearning/tree/master/mybatis_day02