优秀的编程知识分享平台

网站首页 > 技术文章 正文

Mybatis的基础和高级查询应用实践

nanyue 2024-11-21 18:56:16 技术文章 6 ℃

前言

将分为3部分介绍:

  • 基本应用
  • 基于xml的复杂映射开发
  • Mybatis注解开发

[玫瑰][玫瑰]你的“关注”“收藏”是我最大的动力。非常感谢。[玫瑰][玫瑰]

#java##数据库##开发##后端#

基本应用

1.快速入门

快速入门查看官网 :http://www.mybatis.org/mybatis-3

开发步骤

1.添加Mybatis的坐标(添加pom.xml依赖)

<!--mybatis-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
</dependency>
<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
    <scope>runtime</scope>
</dependency>

2.创建数据库表 + 编写实体

表设计和实体根据自己业务实际编写即可

3.编写映射文件Mapper.xml与标签说明


<!--
    <?xml ...>    映射文件DTD约束头
    <mapper>    根标签
        namespae    命名空间,与语句ID标识id组成查询的标识
    <select>    查询操作
    <update>    更新操作
    <insert>    添加操作
    <delete>    删除操作
        id                语句ID标识,与命名空间一起组织成查询标识
        resultType        查询结果对应的实体类型
        parameterType    查询对象类型
-->
<?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="UserMapper">
    <select id="find" resultType="com.otoom.pojo.User" parameterType="com.otoom.pojo.User">
        select * from User WHERE username = #{username}
    </select>
</mapper>

4.编写核心文件SqlMapConfig.xml

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN“ "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="jdbc.properties"/>
       <!--环境,默认环境为:development-->
    <environments default="development">
        <!--环境配置-->
        <environment id="development">
            <!--当前事务交给JDBC处理-->
            <transactionManager type="JDBC"/>
            <!--使用mybatis提供的连接池-->
            <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>
    <!--引入配置文件-->
    <mappers>
        <!--使用指定文件路径
        <mapper resource="com/xxx/mapper/UserMapper.xml"/>
        -->

        <!--
            指定包名,会扫描这个文件夹下所有的xml
            这个xml的路径包名在resource中,需要和接口的包名一致
            如: resources目录下:com/xxx/mapper 存放xml文件
        -->
        <package name="com.xxx.mapper"/>
    </mappers>
</configuration>

5.使用

public static void main(String[] args){
    //获取配置信息
    InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 
    //获取工厂类
    SqlSessionFactory sqlSessionFactory = 
        new SqlSessionFactoryBuilder().build(resourceAsStream); 
    //开启sql会话
    SqlSession sqlSession = sqlSessionFactory.openSession(); 
    //开始执行对应操作
    User query = new User();
    query.setUsername("Tom"); 
    int insert = sqlSession.insert("userMapper.find", query);
    //提交事务 
    //sqlSession.commit(); //CUD操作需要提交事务
    //关闭会话
    sqlSession.close();
}

sqlConfig.xml核心配置文件标签说明

<environments>: 数据库环境的配置,支持多种环境配置

<environment>: 环境变量

<transactionManager>: 事务管理器,有两种类型:

  1. JDBC:使用了JDBC的提交和回滚设置,依赖于从数据源得到的链接来管理事务作用域
  2. MANAGED:这个配置几乎什么都没有做,它从不提交和回滚一个链接,而是让容器去管理事务的整个生命周期。默认情况下它会关闭连接,然后有些容器不希望关闭,所以需要将 closeConnection 属性设置为false来阻止它的默认行为

<dataSource>: 数据源,有三种类型:

  1. UNPOOLED:非连接池类型。这个数据源实现的只是每次请求时打开和关闭连接
  2. POOLED:连接池类型。这种数据源实现利用"池"的概念将JDBC连接对象组织起来
  3. JNDI:这个数据源实现是为了能在如EJB或者应用服务器这类的容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文引用

<property>: 属性

<propertys>: 属性该标签可以加载额外配置的properties文件,如resource文件夹下的jdbc.properties。使用方式为:${jdbc.driver} 可以引用对应的值

<mappers>: 映射器,作用是加载sql的映射,有四种方式

  1. 使用类路径:<mapper resource="com/xxx/mapper/UserDao.xml"/>
  2. 使用完全限定资源定位符(URL): <mapper url="file:///user/xx/project/xxx/UserDao.xml"/>
  3. 使用映射器接口实现类的完全限定类名: <mapper class="com.xxx.UserDao"/>
  4. 使用包内的映射器接口实现全部注册为映射器: <package name="com.xxx.mapper"/>

基于xml复杂映射开发

准备:演示说明具体的xml复杂映射开发前,需要准备一下模拟信息

- 实体

- Mapper接口

  • 实体(对应数据库表)
public class User{
    private Integer id;
    private String userName;
    //一个用户,有多个订单(一对多)
    private List<Order> orderList;
    //用户角色(多对多)
    private List<Role> roleList;
}
public class Order{
    private Integer id;
    private Integer userId;
    private String orderTime;
    //一个订单,只有一个用户(一对一)
    private User user;
}
public class Role{
    private Integer id;
    private String roleName;
}
public class UserRole{
    private Integer userId
    private Integer roleid;
}
  • Mapper接口
public class OrderMapper{
    List<Order> findAll();
    //查询一对一
    List<Order> finUserAndOrder();
}
public class UserMapper{
    User findById(Integer userId);
    //查询一对多
    List<User> findAll();
    //查询多对对
    List<User> findAllUserAndRole();
}
public class RoleMapper{
    //查询多对对
    List<Role> findByUserId(Integer userId);
}

一对一查询

<mapper namespace="OrderMapper">
    <!--一对一映射配置-->
    <resultMap id="orderMap" type="Order">
        <result property="id" column="id"/>
        <result property="userId" column="userId"/>
        <result property="orderTime" column="orderTime"/>
        <!--
            这里配置User对象里面的user属性的User对象与表字段的映射关系
            实现把user和order的一对一关系映射
        -->
        <association property="user" javaType="User">
            <result property="id" column="userId"/>
            <result property="username" column="username"/>
        </association>
    </resultMap>

    <!--resultMap: 手动配置实体属性与表字段的映射关系-->
    <select id="finUserAndOrder" parameterType="Order" resultMap="orderMap">
        select * from order o,user u where o.userId = u.id
    </select>
</mapper>

一对多查询

从用户角度出发,查询一对多结果;

<mapper namespace="UserMapper">
    <!--一对多映射配置-->
    <resultMap id="userMap" type="User">
        <result property="id" column="id"/>
        <result property="username" column="username"/>
        <!--这里配置orderList属性的Order对象与表字段的映射关系-->
        <collection property="orderList" ofType="Order">
            <result property="id" column="oid"/>
            <result property="userId" column="userId"/>
            <result property="orderTime" column="orderTime"/>
        </collection>
    </resultMap>
    <!--resultMap: 手动配置实体属性与表字段的映射关系-->
    <select id="findAll" parameterType="User" resultMap="userMap">
        select *,o.id oid from user u left join order o on o.userId = u.id
    </select>
</mapper>

多对多查询

用户和角色的关系,就是多对多查询;

<mapper namespace="UserMapper">
    <!--多对多映射配置-->
    <resultMap id="userRoleMap" type="User">
        <result property="id" column="id"/>
        <result property="username" column="username"/>
        <!--这里配置roleList属性的Role对象与表字段的映射关系-->
        <collection property="roleList" ofType="Role">
            <result property="id" column="rid"/>
            <result property="roleName" column="roleName"/>
        </collection>
    </resultMap>
    <select id="findAllUserAndRole" parameterType="User" resultMap="userRoleMap">
        select u.*,r.*,r.id rid from user u 
            left join user_role ur on u.id = ur.userId
            left join role r on r.id = ur.roleId
    </select>
</mapper>

测试复杂映射

public static void main(String[] args){
    //获取配置输入流
    InputStream inputStream = Resources.getResourceAsSteam("splMapConfig.xml");
    //获取sql会话
    SqlSession sqlSession = SqlSessionFactoryBuilder.build(inputStream).openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //执行查询

    /*一对一*/
    List<Order> orderList = orderMapper.finUserAndOrder();
    for(Order order : orderList){
        System.out.println(order)
    }
    /*一对多*/
    List<User> userList = userMapper.findAll();
    for(User user : userList){
        System.out.println(user)
    }
    /*多对多*/
    List<User> userList = userMapper.findAllUserAndRole();
    for(User user : userList){
        System.out.println(user)
    }
    sqlSession.close();
}

Mybatis注解开发

常用注解:使用注解开发前,先介绍以下常用的注解

  • @Insert 新增
  • @Update 更新
  • @Delete 删除
  • @Select 查询
  • @Result 实现结果集封装。代替了xml中的和标签,有以下属性:
  1. column 数据库的字段名
  2. property 对应对象的属性名one 需要使用的@One注解 :@Result( one=@One )
  3. many 需要使用@Many注解:@Result( many=@Many )
  • @Results 可以与@Result一起使用,封装多个结果集
  • 代替了xml中的标签,也可以使用@Result集合,使用格式:
@Results({
      @Result(),@Result()
  })
  • @One 一对一结果集封装

代替了标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。有以下属性:

  1. select 指定用来多表查询的 sqlmapper
@Result(column="",property="",one=@One(select=""))
  • @Many 一对多结果集封装

代替了标签,是多表查询的关键,再注解中用来指定子查询返回的对象集合。有以下属性:

  1. select 指定用来多表查询的 sqlmapper
@Result(column="",property="",one=@Many(select=""))

使用注解一对一查询

public class OrderMapper{
    //查询一对一
    @Select("select * from order")
    @Results({
        @Result(id=true,property="id",column="id"),
        @Result(property="userId",column="userId"),
        @Result(property="orderTime",column="orderTime")
        @Result(property="user",column="userId",
                javaType=User.class,
                one=@One(select="com.xxx.mapper.UserMapper.findById")
               )
    })
    List<Order> finUserAndOrder();
}
public class UserMapper{
    @Select("select * from user where id=#{userId}")
    User findById(Integer userId);
}

使用注解一对多查询

public class OrderMapper{    
    @Select("select * from order where userId=#{userId}")
    List<Order> findByUserId(Integer userId);
}
public class UserMapper{
    //查询一对多
    @Select("select * from user")
    @Results({
        @Result(id=true,property="id",column="id"),
        @Result(id=true,property="username",column="username"),
        @Result(property="orderList",column="id",
                javaType=List.class,
                many=@Many(select="com.xxx.mapper.OrderMapper.findByUserId")
    })
    List<User> findAllUserAndOrder();
}

使用注解多对多查询

public class UserMapper{
    //查询多对对
    @Select("select * from user")
    @Results({
        @Result(id=true,property="id",column="id"),
        @Result(property="username",column="username"),
        @Result(property="roleList",column="id",
               javaType=List.class,
               many=@Many(select="com.xxx.mapper.RoleMapper.findByUserId"))
    })
    List<User> findAllUserAndRole();
}
public class RoleMapper{
    //查询多对对
    @Select("select * from role r,user_role ur where r.id=ur.roleId and ur.userId = #{userId}")
    List<Role> findByUserId(Integer userId);
}

结语

以上是对mybatis的基础使用和高级用法,实际项目中,可以结合情况,使用xml查询或者使用两者结合查询都是可行的。

可以的话,麻烦“关注”一下哦。后续文章中,会继续介绍mybatis的缓存和插件机制。

快捷访问:Mybatis一级缓存和二级缓存

Tags:

最近发表
标签列表