0
点赞
收藏
分享

微信扫一扫

Mybatis框架(Dao层实现+文件深入+多表操作)



Mybatis框架(Dao层实现+文件深入+多表操作)

  • ​​1 Mybatis代理开发方式实现Dao层​​
  • ​​2 Mybatis文件深入​​
  • ​​2.1 映射文件深入(动态SQL)​​
  • ​​2.1.1 动态sql-if​​
  • ​​2.1.2 动态sql-foreach​​
  • ​​2.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的类型相同

Mybatis框架(Dao层实现+文件深入+多表操作)_mybatis

Mybatis框架(Dao层实现+文件深入+多表操作)_后端_02

1)dao层接口:

public interface UserMapper {
public List<User> findAll() throws IOException;

public User findById(int id);
}

2)映射文件配置:

<?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="lifeilin.dao.UserMapper">
<!-- 查询操作-->
<select id="findAll" resultType="user">
select *
from user
</select>

<!-- 根据id查询用户信息-->
<select id="findById" parameterType="int" resultType="user">
select *
from user
where id = #{id}
</select>
</mapper>

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<User> userList = mapper.findAll();
System.out.println(userList);
//测试有参数方法
User user = mapper.findById(3);
System.out.println(user);
}
}

Mybatis框架(Dao层实现+文件深入+多表操作)_mybatis_03

2 Mybatis文件深入

2.1 映射文件深入(动态SQL)

2.1.1 动态sql-if

根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件。

接口:

public interface UserMapper {
public List<User> findByCondition(User user);
}
<mapper namespace="lifeilin.mapper.UserMapper">
<!-- 查询操作-->
<select id="findByCondition" parameterType="user" resultType="user">
select *
from user
<where>
-- 根据传进来的参数,如果满足if则动态拼接字符串查询
<if test="id!=0">
id = #{id}
</if>
<if test="username!=null">
and username = #{username}
</if>
<if test="password!=null">
and password = #{password}
</if>
</where>
</select>
</mapper>
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<User> userList = mapper.findByCondition(user);
System.out.println(userList);

}
}

Mybatis框架(Dao层实现+文件深入+多表操作)_mybatis_04

2.1.2 动态sql-foreach

业务场景:查询id为1,2,3…的用户的信息

接口:

public List<User> findByIds(List<Integer> ids);

映射文件:

<?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="lifeilin.mapper.UserMapper">
<select id="findByIds" parameterType="list" resultType="user">
select *
from user
<where>
<foreach collection="list" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
</mapper>

测试:

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<Integer> list = new ArrayList<>();
list.add(1);
List<User> userList = mapper.findByIds(list);
System.out.println(userList);

}
}

2.1.3 动态sql的抽取

Mybatis框架(Dao层实现+文件深入+多表操作)_java_05

Mybatis框架(Dao层实现+文件深入+多表操作)_后端_06

2.2 核心配置文件深入

2.2.1 typeHandlers标签

Mybatis框架(Dao层实现+文件深入+多表操作)_后端_07

自定义typeHandlers标签

可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现
org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个JDBC类型。

需求:一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来时换成java的Date,即java的Date与数据库的varchar毫秒值之间转换。

1)创建环境:

创建表:

Mybatis框架(Dao层实现+文件深入+多表操作)_spring_08

接口:

public interface UserMapper {
public void save(User user);
}

映射文件:

<?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="lifeilin.mapper.UserMapper">
<insert id="save" parameterType="user">
insert into user
values (#{id}, #{username}, #{password}, #{birthday})
</insert>
</mapper>

测试:

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();
}
}

报错:

Mybatis框架(Dao层实现+文件深入+多表操作)_maven_09

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<Date> {

// 将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核心配置文件中进行注册

<!--    注册类型处理器-->
<typeHandlers>
<typeHandler handler="lifeilin.handler.DateTypeHandler"></typeHandler>
</typeHandlers>

④ 测试换是否正确

测试存数据:

Mybatis框架(Dao层实现+文件深入+多表操作)_java_10

测试取数据:

Mybatis框架(Dao层实现+文件深入+多表操作)_maven_11

2.2.2 plugins标签(PageHelper分页)

① 导入通用PageHelper的坐标

<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>

② 在mybatis核心配置文件中配置PageHelper插件

<!--    配置分页助手插件:一般在mappers之前-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 指定方言-->
<property name="dialect" value="mysql"/>
</plugin>
</plugins>

③ 测试分页数据获取

@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<User> userList = mapper.findAll();
for (User user : userList
) {
System.out.println(user);
}
//其他分页的数据
PageInfo<User> pageInfo = new PageInfo<User>(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();
}

Mybatis框架(Dao层实现+文件深入+多表操作)_mybatis_12

3 Mybatis的多表操作

3.1 一对一查询

业务场景:order和user,根据查询order中的属性(包含user的id),将user中的属性也一起查询出来。

1)User实体:

Mybatis框架(Dao层实现+文件深入+多表操作)_java_13

2)Order实体:

Mybatis框架(Dao层实现+文件深入+多表操作)_mybatis_14

3)在映射文件中手动配置字段与实体的映射关系:

Mybatis框架(Dao层实现+文件深入+多表操作)_spring_15

<?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="lifeilin.mapper.OrderMapper">
<resultMap id="orderMap" type="lifeilin.domain.Order">
<!--手动指定字段与实体属性的映射关系
column:字段名称
property:实体属性名称
-->
<id column="oid" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
<result column="uid" property="user.id"></result>
<result column="username" property="user.username"></result>
<result column="password" property="user.password"></result>
<result column="birthday" property="user.birthday"></result>
</resultMap>

<select id="findAll" resultMap="orderMap">
SELECT *,
`order`.id oid
FROM `order`,
`user`
WHERE `order`.uid = `user`.id;
</select>
</mapper>

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<Order> orderList = mapper.findAll();
for (Order order:orderList
) {
System.out.println(order);
}

sqlSession.close();
}
}

Mybatis框架(Dao层实现+文件深入+多表操作)_maven_16

Mybatis框架(Dao层实现+文件深入+多表操作)_mybatis_17

5)第二种在映射文件中手动配置字段与实体的映射关系的方法:

Mybatis框架(Dao层实现+文件深入+多表操作)_maven_18

<?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="lifeilin.mapper.OrderMapper">
<resultMap id="orderMap" type="lifeilin.domain.Order">
<!--手动指定字段与实体属性的映射关系
column:字段名称
property:实体属性名称
-->
<id column="oid" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
<!-- property:当前实体(order)中的属性名称(private User user)-->
<!-- javaType:当前实体(order)中的属性类型(User),这里使用了别名(user)-->
<association property="user" javaType="lifeilin.domain.user">
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
</association>
</resultMap>

<select id="findAll" resultMap="orderMap">
SELECT *,
`order`.id oid
FROM `order`,
`user`
WHERE `order`.uid = `user`.id;
</select>
</mapper>

3.2 一对多查询

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

Mybatis框架(Dao层实现+文件深入+多表操作)_后端_19

Mybatis框架(Dao层实现+文件深入+多表操作)_后端_20

<?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="lifeilin.mapper.UserMapper">
<resultMap id="userMap" type="lifeilin.domain.user">
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!-- 配置集合信息
property:集合名称
ofType:当前集合中的数据类型
-->
<collection property="orderList" ofType="lifeilin.domain.order">
<!-- 封装order数据-->
<id column="oid" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
</collection>
</resultMap>

<select id="findUserAll" resultMap="userMap">
SELECT *,
o.id oid
FROM `user` u,
`order` o
WHERE u.id = o.uid;
</select>
</mapper>

Mybatis框架(Dao层实现+文件深入+多表操作)_spring_21

3.3 多对多查询

Mybatis框架(Dao层实现+文件深入+多表操作)_spring_22

Mybatis框架(Dao层实现+文件深入+多表操作)_后端_23

<?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="lifeilin.mapper.UserMapper">
<resultMap id="userAndRole" type="lifeilin.domain.User">
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<collection property="roleList" ofType="lifeilin.domain.Role">
<id column="roleId" property="id"></id>
<id column="roleName" property="roleName"></id>
<id column="roleDesc" property="roleDesc"></id>
</collection>
</resultMap>
<select id="findUserAndRole" resultMap="userAndRole">
SELECT *
FROM `user` u,
sys_user_role ur,
sys_role r
WHERE u.id = ur.userId
AND ur.roleId = r.id
</select>
</mapper>

Mybatis框架(Dao层实现+文件深入+多表操作)_java_24



举报

相关推荐

0 条评论