1 Mybatis代理开发方式实现Dao层2 Mybatis文件深入
2.1 映射文件深入(动态SQL)
2.1.1 动态sql-if2.1.2 动态sql-foreach2.1.3 动态sql的抽取 2.2 核心配置文件深入
2.2.1 typeHandlers标签2.2.2 plugins标签(PageHelper分页) 3 Mybatis的多表操作
3.1 一对一查询3.2 一对多查询3.3 多对多查询
1 Mybatis代理开发方式实现Dao层采用 Mybatis 的代理开发方式实现 DAO 层的开发,这种方式是我们后面进入企业的主流。Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper 接口开发需要遵循以下规范: 1、 Mapper.xml文件中的namespace与mapper接口的全限定名相同 2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同 3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同 4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
1)dao层接口:
public interface UserMapper {
public List findAll() throws IOException;
public User findById(int id);
}
2)映射文件配置:
select * from user
3)测试代码:
public class ServiceTest {
public static void main(String[] args) throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//参数写接口类型
// 测试无参数方法
List userList = mapper.findAll();
System.out.println(userList);
//测试有参数方法
User user = mapper.findById(3);
System.out.println(user);
}
}
2 Mybatis文件深入
2.1 映射文件深入(动态SQL)
2.1.1 动态sql-if
根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件。
接口:
public interface UserMapper {
public List findByCondition(User user);
}
public class MapperTest {
@Test
public void test() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//模拟参数条件user
User user = new User();
user.setId(3);
user.setUsername("张无忌");
// user.setPassword("123456");
List userList = mapper.findByCondition(user);
System.out.println(userList);
}
}
2.1.2 动态sql-foreach
业务场景:查询id为1,2,3…的用户的信息
接口:
public ListfindByIds(List ids);
映射文件:
测试:
public class MapperTest {
@Test
public void test() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
ArrayList list = new ArrayList<>();
list.add(1);
List userList = mapper.findByIds(list);
System.out.println(userList);
}
}
2.1.3 动态sql的抽取
自定义typeHandlers标签
可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现
org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类org.apache.ibatis.type.baseTypeHandler, 然后可以选择性地将它映射到一个JDBC类型。
需求:一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来时转换成java的Date,即java的Date与数据库的varchar毫秒值之间转换。
1)创建环境:
创建表:
接口:
public interface UserMapper {
public void save(User user);
}
映射文件:
insert into user values (#{id}, #{username}, #{password}, #{birthday})
测试:
public class UserMapperTest {
@Test
public void test() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(4);
user.setUsername("lifeilin");
user.setPassword("0000");
user.setBirthday(new Date()); //将Date类型转成表中的int类型会报错
mapper.save(user);
sqlSession.commit();
sqlSession.close();
}
}
报错:
2)自定义类型转换标签
① 定义转换类继承类baseTypeHandler
② 覆盖4个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时 mysql的字符串类型转换成 java的Type类型的方法
import org.apache.ibatis.type.baseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Date; public class DateTypeHandler extends baseTypeHandler{ // 将Java类型转换成数据库中的类型 @Override public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException { long time = date.getTime(); preparedStatement.setLong(i, time); } //将数据库中类型转成Java需要的类型 // String : 要转换字段的名字 // ResultSet : 查询结果集 @Override public Date getNullableResult(ResultSet resultSet, String s) throws SQLException { //将long型转为Date long aLong = resultSet.getLong(s); Date date = new Date(aLong); return date; } //将数据库中类型转成Java需要的类型 @Override public Date getNullableResult(ResultSet resultSet, int i) throws SQLException { //将long型转为Date long aLong = resultSet.getLong(i); Date date = new Date(aLong); return date; } //将数据库中类型转成Java需要的类型 @Override public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException { //将long型转为Date long aLong = callableStatement.getLong(i); Date date = new Date(aLong); return date; } }
③ 在MyBatis核心配置文件中进行注册
④ 测试转换是否正确
测试存数据:
测试取数据:
① 导入通用PageHelper的坐标
com.github.pagehelper pagehelper 3.7.5 com.github.jsqlparser jsqlparser 0.9.1
② 在mybatis核心配置文件中配置PageHelper插件
③ 测试分页数据获取
@Test
//查询全部
public void test3() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//设置分页相关参数 当前页+每页显示条数
PageHelper.startPage(1,3);
List userList = mapper.findAll();
for (User user : userList
) {
System.out.println(user);
}
//其他分页的数据
PageInfo pageInfo = new PageInfo(userList);
System.out.println("总条数:"+pageInfo.getTotal());
System.out.println("总页数:"+pageInfo.getPages());
System.out.println("当前页:"+pageInfo.getPageNum());
System.out.println("每页显示长度:"+pageInfo.getPageSize());
System.out.println("是否第一页:"+pageInfo.isIsFirstPage());
System.out.println("是否最后一页:"+pageInfo.isIsLastPage());
sqlSession.close();
}
3 Mybatis的多表操作
3.1 一对一查询
业务场景:order和user,根据查询order中的属性(包含user的id),将user中的属性也一起查询出来。
1)User实体:
2)Order实体:
3)在映射文件中手动配置字段与实体的映射关系:
4)测试:
public class OrderMapperTest {
@Test
public void test() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
List orderList = mapper.findAll();
for (Order order:orderList
) {
System.out.println(order);
}
sqlSession.close();
}
}
5)第二种在映射文件中手动配置字段与实体的映射关系的方法:
3.2 一对多查询
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单
3.3 多对多查询



