项目管理与SSM框架 MyBatis(五)

本文涉及的产品
RDS AI 助手,专业版
RDS Agent(兼容OpenClaw),2核4GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: 项目管理与SSM框架 MyBatis(五)

十、MyBatis注解开发

  1. 创建maven工程,引入依赖
  2. 创建mybatis核心配置文件SqlMapConfig.xml
  3. 将log4j.properties文件放入resources中,让控制台打印SQL语句。
  4. 创建实体类
  5. 创建持久层接口,并在接口方法上定义Sql语句
public interface UserMapper {
  @Select("select * from user")
  List<User> findAll();
}

由于注解在方法上方,而方法中就有参数类型和返回值类型,所以使用注解开发不需要定义参数类型和返回值类型

6、在核心配置文件注册持久层接口,由于没有映射文件,所以只能采用注册接口或注册包的方法。

<!--基于注解开发的话,没有映射文件就注册接口-->
    <mappers>
       <package name="com.zj.mapper"/>
    </mappers>

7、测试方法

@Test
    public void testFindAllUsers(){
        List<User> allUsers = userMapper.findAllUsers();
        for (User allUser : allUsers) {
            System.out.println(allUser);
        }
    }

10.1 基于注解实现增删改查

@Select("select * from user")
    List<User> findAllUsers();
    @SelectKey(keyColumn = "id",keyProperty = "id",resultType = int.class,before = false,
              statement = "select LAST_INSERT_ID()")
    @Insert("insert into user values (default, #{username}, #{sex},#{address})")
    void addUser(User user);
    @Delete("delete from user where id = #{id}")
    void removeUser(int id);
    @Update("update user set username = #{username}, sex = #{sex}, address = #{address}" +
            "where id = #{id}")
    void updateUser(User user);
    @Select("select * from user where username like #{username}")
    List<User> findUserLike(String username);

10.2 动态sql

MyBatis注解开发中有两种方式构建动态Sql:

使用脚本标签(了解即可千万别用,又臭又长)

将Sql嵌套在<script>内即可使用动态Sql标签:

// 根据任意条件查询
@Select("<script>" +
    "  select * from user\n" +
    "     <where>\n" +
    "       <if test=\"username != null and username.length() != 0\">\n" +
    "         username like #{username}\n" +
    "       </if>\n" +
    "       <if test=\"sex != null and sex.length() != 0\">\n" +
    "         and sex = #{sex}\n" +
    "       </if>\n" +
    "       <if test=\"address != null and address.length() != 0\">\n" +
    "         and address = #{address}\n" +
    "       </if>\n" +
    "     </where>" +
    "</script>")
List<User> findByCondition(User user);

在方法中构建动态Sql

在MyBatis中有@SelectProvider@UpdateProvider@DeleteProvider@InsertProvider注解。当使用这些注解时将不在注解中直接编写SQL,而是调用某个类的方法来生成SQL。

1、创建类构建sql语句

package com.zj.provider;
import com.zj.pojo.User;
/*构建sql*/
public class UserProvider {
        //生成根据任意条件查询的sql语句
    public String findByConditionSql(User user){
        StringBuffer sb = new StringBuffer("SELECT * FROM  user WHERE 1=1");
        if (user.getUsername() != null && user.getUsername().length() > 0){
            sb.append(" and username = #{username}");
        }
        if (user.getSex() != null && user.getSex().length() > 0){
            sb.append(" and sex = #{sex}");
        }
        if (user.getAddress() != null && user.getAddress().length() > 0){
            sb.append(" and address = #{address}");
        }
        return sb.toString();
    }
}

2、持久层

/*根据任意给定条件查询用户,使用某个类构建sql*/
    @SelectProvider(type = UserProvider.class,method = "findByConditionSql")
    List<User> findByConditionSql(User user);

3、测试

@Test
    public void testFindByConditionSql(){
        User user = new User();
        user.setUsername("顾田然");
        List<User> users = userMapper.findByConditionSql(user);
        for (User user1 : users) {
            System.out.println(user1);
        }
    }

10.3 自定义映射

当POJO属性名与数据库列名不一致时,需要自定义实体类和结果集的映射关系,在MyBatis注解开发中,使用@Results定义并使用自定义映射,使用@ResultMap使用自定义映射,用法如下:

/*自定义映射*/
    @Results(id = "userMapper",value = {
            @Result(id = true,property = "id",column = "id"),
            @Result(property = "username",column = "username"),
            @Result(property = "sex",column = "sex"),
            @Result(property = "address",column = "address")
    })
    @Select("select * from user")
    List<User> findAllUsers();

10.4 基于注解开启二级缓存

1、POJO类实现Serializable接口。

2、在持久层接口上方加注解@CacheNamespace(blocking=true),该接口的所有方法都支持二级缓存。

@CacheNamespace(blocking = true)
public interface UserMapper {
……
}

10.5 基于注解实现一对一关联查询

在MyBatis的注解开发中对于多表查询只支持分解查询(N+1),不支持连接查询。

1、创建实体类

public class Student {
  private int sid;
  private String name;
  private int age;
  private String sex;
  private Classes classes;
  // 省略getter/setter/toString
}
public class Classes {
  private int cid;
  private String className;
  private List<Student> students;
  // 省略getter/setter/toString
}

2、持久层

package com.zj.mapper;
import com.zj.pojo.Student;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface StudentMapper {
    //查询全部学生
    @Results(id = "StudentMapper" ,value = {
            @Result(id = true,property = "sid",column = "sid"),
            @Result(property = "name",column = "name"),
            @Result(property = "age",column = "age"),
            @Result(property = "sex",column = "sex"),
            //调用查询时传入的参数是哪列
            @Result(property = "classes",column = "classId",
                    one = @One(select = "com.zj.mapper.ClassesMapper.findClassById",
                    fetchType = FetchType.EAGER)
            )
    })
    @Select("select * from Student")
    List<Student> findAllStudent();
}
package com.zj.mapper;
import com.zj.pojo.Classes;
import org.apache.ibatis.annotations.Select;
public interface ClassesMapper {
    //根据班级cid查询班级信息
    @Select("select * from classes where cid = #{cid}")
    Classes findClassById(int cid);;
}

3、测试

@Test
    public void testStudentMapper() {
        List<Student> allStudent = studentMapper.findAllStudent();
        for (Student student : allStudent) {
            System.out.println(student);
        }
    }

10.6 基于注解实现一对多关联查询

查询班级信息的时候将该班级下的学生一起查出来。

1、持久层

//查询全部班级(一对多一般使用懒加载)
    @Results(id = "classesMap",value = {
            @Result(id = true,property = "cid",column = "cid"),
            @Result(property = "className",column = "className"),
            @Result(property = "studentList",column = "cid",
            many = @Many(select="com.zj.mapper.StudentMapper.findStudentByCid",
            fetchType = FetchType.LAZY))
    })
    @Select("select * from classes")
    List<Classes> findAllClasses();
    //根据班级id查询学生
    @Select("select * from student where classId = #{classId}")
    Student findStudentByCid(int classId);

2、测试

@Test
    public void testFindAllClasses(){
        List<Classes> allClasses = classesMapper.findAllClasses();
        for (Classes allClass : allClasses) {
            System.out.println(allClass);
        }
    }

10.7 注解和映射文件对比

MyBatis中更推荐使用映射文件开发,Spring、SpringBoot更推荐注解方式。具体使用要视项目情况而定。它们的优点对比如下:

映射文件:

  • 代码与Sql语句是解耦的,修改时只需修改配置文件,无需修改源码。
  • Sql语句集中,利于快速了解和维护项目。
  • 级联查询支持连接查询和分解查询两种方式,注解开发只支持分解查询。

注解:

  • 配置简单,开发效率高。
  • 类型安全,在编译期即可进行校验,不用等到运行时才发现错误。

十一、PageHelper分页插件

开发过程中如果要进行分页查询,需要传入页数和每页条数。返回页面数据,总条数,总页数,当前页面,每页条数等数据。此时使用PageHelper插件可以快速帮助我们获取这些数据。

PageHelper是一款非常好用的开源免费的Mybatis第三方分页插件。使用该插件时,只要传入分页参数,即可自动生成页面对象。我们使用该插件分页查询所有用户:

1、引入依赖

<!-- PageHelper -->
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.3.0</version>
</dependency>

2、Mybatis配置文件中配置PageHelper插件

<plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- 设置数据库类型-->
            <property name="helperDialect" value="mysql"/>
        </plugin>
    </plugins>

3、测试

@Test
    public void testFindAllUsers(){
        //1、设置分页参数
        Page<Object> objects = PageHelper.startPage(1, 3);
        //查询数据库
        List<User> allUsers = userMapper.findAllUsers();
        //封装查询结果生成页面对象
        PageInfo<User> pageInfo = new PageInfo(allUsers);
        //打印页面数据
        List<User> list = pageInfo.getList();
        System.out.println("结果集:"+list);
        System.out.println("总条数:"+pageInfo.getTotal());
        System.out.println("总页数:"+pageInfo.getPages());
        System.out.println("当前页:"+pageInfo.getPageNum());
        System.out.println("每页条数:"+pageInfo.getSize());
    }

十二、MyBatis Generator

MyBatis Generator(MBG)是MyBatis官方提供的代码生成器。它可以根据数据库的表结构自动生成POJO类、持久层接口与映射文件,极大减少了代码的编写量,提高开发效率。

MBG可以作为项目引入使用,也可以作为Maven插件使用,其中作为Maven插件使用更加方便快捷。

1、准备数据库表

2、在pom文件中配置MBG插件

<build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.4.2</version>
                <!--MBG配置-->
                <configuration>
                    <!--配置文件的位置-->
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                    <!--运行显示详情-->
                    <verbose>true</verbose>
                    <!--允许文件覆盖-->
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
    </build>

3、编写MBG配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!-- jdbc的jar包位置,插件需要连接数据库 -->
    <classPathEntry location="D:\Java\apache-maven-3.8.3\repositories\mysql\mysql-connector-java\8.0.26\mysql-connector-java-8.0.26.jar"/>
    <context id="default" targetRuntime="MyBatis3">
        <!-- 是否去除自动生成的注释-->
        <commentGenerator>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--数据库连接参数-->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybatis"
                        userId="root"
                        password="123456">
        </jdbcConnection>
        <!-- 类型处理器,在数据库类型和java类型之间的转换控制-->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- targetProject:POJO类路径  targetProject:生成的POJO类的包(需要提前创建包)-->
        <javaModelGenerator targetProject="src/main/java" targetPackage="com.zj.pojo">
            <!-- 是否生成子包 -->
            <property name="enableSubPackages" value="false"/>
            <!-- 设置是否在getter方法中,对String类型字段调用trim()方法 -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- targetProject:配置文件路径  targetPackage:生成映射文件的位置(要提前创建文件目录) -->
        <sqlMapGenerator targetProject="src/main/resources" targetPackage="com.zj.mapper">
            <!-- 是否生成子包 -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>
        <!-- targetPackage:JAVA类路径 targetProject:生成的持久层接口包 -->
        <javaClientGenerator targetProject="src/main/java" targetPackage="com.zj.mapper" type="XMLMAPPER">
            <!-- 是否生成子包 -->
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>
        <!-- 数据库表(根据哪些表生成,可以写多个table标签),表名不要和其他库中的表名一样 -->
        <table tableName="product"></table>
    </context>
</generatorConfiguration>

4、双击运行插件,自动生成POJO,持久层接口,映射文件:

 

 

  • Product.java:POJO类
  • ProductMapper.java:持久层接口
  • ProductMapper.xml:映射文件
  • ProductExample.java:查询扩展类,该类可以构造复杂的查询条件。
  • Criterion:代表一个字段。
  • GeneratedCriteria:抽象类,生成查询条件的工具。
  • Criteria:GeneratedCriteria的子类,生成查询条件的工具。

12.1 增删改方法

注意在生成插件后还要搭建mybatis,再添加上配置文件。

//添加
    @Test
   public void testAdd(){
       Product product = new Product(0,"英特尔(Intel) i7-13700K 13代 酷睿 处理器",2999.0);
       int insert = productMapper.insert(product);
       sqlSession.commit();
   }
   //修改
    @Test
    public void testUpdate(){
        Product product = new Product();
        product.setId(3);
        product.setProductname("小天才电话手表");
        product.setPrice(499.0);
        int i = productMapper.updateByPrimaryKey(product);
        sqlSession.commit();
    }
    //删除
    @Test
    public void testDelete(){
        int i = productMapper.deleteByPrimaryKey(2);
        sqlSession.commit();
    }

12.2 查询方法

//根据id查询
    @Test
    public void testFindById(){
        Product product = productMapper.selectByPrimaryKey(1);
        System.out.println(product);
    }
    //查询全部
    @Test
    public void testFindAll(){
        /*除了根据id查询之外其他的查询方法都需要使用查询扩展对象来构建查询条件*/
        ProductExample productExample = new ProductExample();
        /*查询全部不需要构建查询条件*/
        List<Product> products = productMapper.selectByExample(productExample);
        for (Product product : products) {
            System.out.println(product);
        }
    }
    //根据名称查询
    @Test
    public void testFindByName(){
        /*构建查询条件*/
        ProductExample productExample = new ProductExample();
        ProductExample.Criteria criteria = productExample.createCriteria();
        criteria.andProductnameLike("%华为Mate40%");
        /*查询*/
        List<Product> products = productMapper.selectByExample(productExample);
        for (Product product : products) {
            System.out.println(product);
        }
    }

12.3复杂查询

//多条件的and查询
    @Test
    public void testFindAnd(){
        /*构建查询条件*/
        ProductExample productExample = new ProductExample();
        ProductExample.Criteria criteria = productExample.createCriteria();
        criteria.andProductnameLike("%华为%");
        criteria.andPriceBetween(3000.0,10000.0);
        List<Product> products = productMapper.selectByExample(productExample);
        for (Product product : products) {
            System.out.println(product);
        }
    }
    //多条件的or查询
    @Test
    public void testFindOr(){
        /*构建查询条件1*/
        ProductExample productExample = new ProductExample();
        ProductExample.Criteria criteria1 = productExample.createCriteria();
        criteria1.andProductnameLike("%华为%");
        /*构建查询条件2*/
        ProductExample.Criteria criteria2 = productExample.createCriteria();
        criteria2.andPriceBetween(8000.0,10000.0);
        /*创建or关系(括号中只放第二个)*/
        productExample.or(criteria2);
        /*查询*/
        List<Product> products = productMapper.selectByExample(productExample);
        for (Product product : products) {
            System.out.println(product);
        }
    }


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
SQL XML Java
350 0
|
9月前
|
SQL Java 数据库连接
区分iBatis与MyBatis:两个Java数据库框架的比较
总结起来:虽然从技术角度看,iBATIS已经停止更新但仍然可用;然而考虑到长期项目健康度及未来可能需求变化情况下MYBATISS无疑会是一个更佳选择因其具备良好生命周期管理机制同时也因为社区力量背书确保问题修复新特征添加速度快捷有效.
777 12
|
10月前
|
SQL XML Java
MyBatis框架如何处理字符串相等的判断条件。
总的来说,MyBatis框架提供了灵活而强大的机制来处理SQL语句中的字符串相等判断条件。无论是简单的等值判断,还是复杂的条件逻辑,MyBatis都能通过其标签和属性来实现,使得动态SQL的编写既安全又高效。
747 0
|
11月前
|
SQL Java 数据库连接
2-SSM框架篇
Spring框架核心知识点总结,涵盖IOC、DI、Bean作用域、事务管理、AOP、Spring MVC流程及MyBatis相关问题。内容包括控制反转与依赖注入原理、Bean生命周期与线程安全、事务传播机制、JDK与CGLIB代理区别、MyBatis动态SQL与缓存机制等高频面试题。
213 0
|
Oracle 关系型数据库 Java
|
SQL 缓存 Java
框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性
本文详细解构了MyBatis的工作机制,包括解析配置、创建连接、执行SQL、结果封装和关闭连接等步骤。文章还介绍了MyBatis的五大核心功能特性:支持动态SQL、缓存机制(一级和二级缓存)、插件扩展、延迟加载和SQL注解,帮助读者深入了解其高效灵活的设计理念。
|
Java 关系型数据库 MySQL
weixin050高校体育场管理系统+ssm(文档+源码)_kaic
本文针对高校体育场管理系统的开发与实现进行详细介绍。随着经济快速发展,人们对手机软件需求增加,高校体育场管理系统应运而生。系统采用JAVA技术、Mysql数据库和SSM框架等成熟技术,通过分析功能需求、可行性及性能,设计出包含管理员、用户和学生角色的功能模块。系统实现用户注册登录、信息管理等功能,简化传统手工统计模式,提高管理效率,满足用户对信息获取的及时性与准确性需求。
weixin050高校体育场管理系统+ssm(文档+源码)_kaic
|
前端开发 Java 关系型数据库
基于ssm的社区物业管理系统,附源码+数据库+论文+任务书
社区物业管理系统采用B/S架构,基于Java语言开发,使用MySQL数据库。系统涵盖个人中心、用户管理、楼盘管理、收费管理、停车登记、报修与投诉管理等功能模块,方便管理员及用户操作。前端采用Vue、HTML、JavaScript等技术,后端使用SSM框架。系统支持远程安装调试,确保顺利运行。提供演示视频和详细文档截图,帮助用户快速上手。
572 17
|
前端开发 Java 关系型数据库
基于ssm的台球厅管理系统,附源码+数据库+论文
本项目为新锐台球厅管理系统,支持管理员和会员两种角色。管理员可进行会员管理、台球桌管理、订单管理等;会员可查看台球桌、预约、购买商品等。技术框架基于Java,采用B/S架构,前端使用Vue+HTML+JavaScript+CSS+LayUI,后端使用SSM框架,数据库为MySQL。运行环境为Windows,JDK8+MySQL5.7+Tomcat8.5。提供演示视频及详细文档截图。
|
前端开发 Java 关系型数据库
基于ssm的网络直播带货管理系统,附源码+数据库+论文
该项目为网络直播带货网站,包含管理员和用户两个角色。管理员可进行主页、个人中心、用户管理、商品分类与信息管理、系统及订单管理;用户可浏览主页、管理个人中心、收藏和订单。系统基于Java开发,采用B/S架构,前端使用Vue、JSP等技术,后端为SSM框架,数据库为MySQL。项目运行环境为Windows,支持JDK8、Tomcat8.5。提供演示视频和详细文档截图。
399 10