• 【Spring--SSM框架详解】主流Java后端开发,Mybatis+Spring+SpringMVC整合(更新Spring中)


    BackEnd 学习笔记

    1 Java 

    2 SSM框架(Mybatis+Spring+SpringMVC)

    3 SpringBoot(SpringBoot 3.x+MybatisPlus)

    4 SpringCloud

    5 Redis(Redis6)

    6 ZooKeeper

    7 Dubbo

    8 ActiveMQ

    9 RabbitMQ

    10 RocketMQ

    11 MongoDB

    12 Docker

    13 ServerDeployment

    符号说明

    🔥较火,开发中较多使用,因文章多为干货,因此较难而且重要的才会标此符号

    💧较水,开发中较少使用

    一、SSM

            SSM是市面上最流行的Web开发框架,由SpringMVC、Spring、MyBatis整合而成。其中,SpringMVC负责接收浏览器发送的请求,并响应浏览器数据;Spring使用IOC思想管理服务器中各个组件,使用AOP思想面向切面编程,在不改变源码的基础上实现功能增强;MyBatis封装JDBC,负责访问数据库,完成持久化操作。

    二、Mybatis--持久层框架

    2.1 Introduction

            Mybatis是支持定制化SQL、存储过程以及高级映射的优秀持久层框架,避免了JDBC和手动设置参数,使用XML文件进行配置 

    2.2 IDE 

    2.2.1 Empty project

    创建一个空项目,选择JDK和语言

     配置Maven工具

     设置打包方式和导入依赖类 

    1. <packaging>jarpackaging>
    2. <dependencies>
    3. <dependency>
    4. <groupId>org.mybatisgroupId>
    5. <artifactId>mybatisartifactId>
    6. <version>3.5.10version>
    7. dependency>
    8. <dependency>
    9. <groupId>junitgroupId>
    10. <artifactId>junitartifactId>
    11. <version>4.13.2version>
    12. <scope>testscope>
    13. dependency>
    14. <dependency>
    15. <groupId>mysqlgroupId>
    16. <artifactId>mysql-connector-javaartifactId>
    17. <version>8.0.29version>
    18. dependency>
    19. <dependency>
    20. <groupId>org.projectlombokgroupId>
    21. <artifactId>lombokartifactId>
    22. <version>RELEASEversion>
    23. <scope>compilescope>
    24. dependency>
    25. dependencies>

    安装MybatisX插件

    这个可是宝藏插件了,为提高开发效率而生,其主要功能如下

    • 红蓝小鸟图标,长得好看,点击图标快速跳转对应页面
    • ⭐️提示快速生产xml、sql语句等信息
    • ⭐️逆向工程,详看2.10

    2.2.2 Pojo

    创建实体类对象User

    @Data:ToString()、Getter()、Setter()等一些常见方法

    @AllArgsConstructor:全参构造方法

    @NoArgsConstructor:无参构造方法

    1. package com.bcn.mybatis.pojo;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. /**
    6. * @author 大白菜
    7. * {@code @date} Created in 2022/7/22 12:31
    8. */
    9. @Data
    10. @AllArgsConstructor
    11. @NoArgsConstructor
    12. public class User {
    13. private Integer id;
    14. private String username;
    15. private String password;
    16. private Integer age;
    17. private String gender;
    18. private String email;
    19. }

    2.2.3 Configuration File

    一般叫做mybatis-config.xml,在整合Spring之后,这个配置文件可以直接省略了

    主要用于配置数据库环境、pojo和mapper的映射文件

    放置在src/main/resources目录下

    1. "1.0" encoding="UTF-8" ?>
    2. configuration
    3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    5. <configuration>
    6. <typeAliases>
    7. <package name="com.bcn.mybatis.pojo"/>
    8. typeAliases>
    9. <environments default="development">
    10. <environment id="development">
    11. <transactionManager type="JDBC"/>
    12. <dataSource type="POOLED">
    13. <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
    14. <property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"/>
    15. <property name="username" value="root"/>
    16. <property name="password" value="123456"/>
    17. dataSource>
    18. environment>
    19. environments>
    20. <mappers>
    21. <package name="com.bcn.mybatis.mapper" />
    22. mappers>
    23. configuration>

    注意:
    1 environment:数据库的环境, 小项目一般只有一个,如果环境多了可以使用default来选择

    2 transactionManager:事务管理方式,共两种,一个是JDBC也就是原生的,一个是MANAGED是被管理的,在Spring整合Mybatis的时候是使用这种方式

    2.2.4 Mapper.xml

    相关概念:ORM(Object Relationship Mapping)对象关系映射。

    对象:Java的实体类对象

    关系:关系型数据库

    映射:二者之间的对应关系

    所以~Mapper.xml是MyBatis的映射文件,主要功能是编写SQL语句,位于src/main/resources/com.bcn.mybatis.mapper目录下

    注意:这里的创建com.bcn.mybatis.mapper文件夹时,输入的内容得是com/bcn/mybatis/mapper而不能是com.bcn.mybatis.mapper。该文件夹应该与java目录下的mapper文件夹的名字是一样的额

    要想实现映射无非是关注我们调用了什么接口下的什么方法,因此需要保持两者一致

    调用了什么接口?namespace

    调用了什么方法?id

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.bcn.mybatis.mapper.UserMapper">
    6. <insert id ="insertUser">
    7. insert into t_user values (null,'admin','123456','23','男','123@163.com');
    8. insert>
    9. mapper>

    2.2.5 log4j.xml

    该文件的主要功能是在控制台获取日志信息,方便我们调试错误

    log4j的配置文件名为log4j.xml,存放的位置是src/main/resources目录下,这里的log4j.xml的名字一定不能更改

    1. "1.0" encoding="UTF-8" ?>
    2. log4j:configuration SYSTEM "log4j.dtd">
    3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    4. <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
    5. <param name="Encoding" value="UTF-8" />
    6. <layout class="org.apache.log4j.PatternLayout">
    7. <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS}
    8. %m (%F:%L) \n" />
    9. layout>
    10. appender>
    11. <logger name="java.sql">
    12. <level value="debug" />
    13. logger>
    14. <logger name="org.apache.ibatis">
    15. <level value="info" />
    16. logger>
    17. <root>
    18. <level value="debug" />
    19. <appender-ref ref="STDOUT" />
    20. root>
    21. log4j:configuration>

    2.2.6 Little Test

    其实到了这里,我们已经复现了JSP中的三层架构模式,现在来测试一下

    1. package com.bcn.mybatis;
    2. import com.bcn.mybatis.mapper.UserMapper;
    3. import org.apache.ibatis.io.Resources;
    4. import org.apache.ibatis.session.SqlSession;
    5. import org.apache.ibatis.session.SqlSessionFactory;
    6. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    7. import org.junit.Test;
    8. import java.io.IOException;
    9. import java.io.InputStream;
    10. /**
    11. * @author 大白菜
    12. * @date Created in 2022/7/24 15:28
    13. */
    14. public class test {
    15. @Test
    16. public void testInserter() throws IOException {
    17. //读取MyBatis的核心配置文件
    18. InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
    19. //创建SqlSessionFactoryBuilder对象
    20. SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    21. //通过SqlSessionFactoryBuilder创建sqlSessionFactory对象
    22. SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
    23. //通过SqlSessionFactory创建sqlSession对象,是最终操作数据库的对象
    24. SqlSession sqlSession = sqlSessionFactory.openSession(true);
    25. //通过代理模式创建UserMapper接口的代理实现类对象
    26. UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    27. //调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹映射文件中的SQL标签,并执行标签中的SQL语句
    28. int result = userMapper.insertUser();
    29. System.out.println("The result is "+result);
    30. //commit没有设置有时候数据库读不进去,因为没有提交事务,所以稳妥一点都写上好了
    31. sqlSession.commit();
    32. sqlSession.close();
    33. }
    34. }

    执行结果,这里的输出了log4j配置产生的日志信息。默认结果输出为1就是执行成功了

    小灶知识点

    1 SqlSession是Java Projct 和 Database之间的会话

    2 代理模式:想访问一个正常情况下不能访问的对象,就创建一个该对象的代理对象,主要表现为接口实例化对象

    2.3 Parameters Get

    Mybatis获取参数主要有两种方式:${} 和 #{}

    ${}:本质是字符串拼接,因此若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号

    #{}:本质是占位符赋值,此时为字符串类型或日期类型的字段进行赋值时, 可以自动添加单引号,还能避免SQL注入问题,所以一般都是用#{}

    非实体对象化的参数默认名字是param1,param2等等,如下

    1. <update id="updateUser">
    2. update t_user set username=#{param1},gender=#{param2} where id=#{param3}
    3. update>

    实体对象的参数得是实体对象的属性名,如下

    1. <insert id ="insertUser">
    2. insert into t_user values (null,#{username},#{password},#{age},#{gender},#{email});
    3. insert>

    非实体对象高级版-->@param,这样在mapper.xml文件中统一的命名都是#{属性名},在Mapper中的代码如下

        User getUserById(@Param("id") int id);

    2.4 CRUD

    2.4.1 SqlSessionUtils

    在开发过程中,如果我们遇到一些常用的操,可以创建对应的工具类,放到Utils包里面,随后使用委派模式使用该类对象

    1. package com.bcn.mybatis.utils;
    2. import org.apache.ibatis.io.Resources;
    3. import org.apache.ibatis.session.SqlSession;
    4. import org.apache.ibatis.session.SqlSessionFactory;
    5. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    6. import java.io.IOException;
    7. import java.io.InputStream;
    8. /**
    9. * @author 大白菜
    10. * @date Created in 2022/7/24 16:24
    11. */
    12. public class SqlSessionUtil {
    13. public static SqlSession getSqlSession(){
    14. SqlSession sqlSession=null;
    15. try {
    16. InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
    17. SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    18. SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
    19. sqlSession = sqlSessionFactory.openSession(true);
    20. } catch (IOException e) {
    21. throw new RuntimeException(e);
    22. }
    23. return sqlSession;
    24. }
    25. }

    2.4.2 CRUD

    UserMapper.java

    1. package com.bcn.mybatis.mapper;
    2. import com.bcn.mybatis.pojo.User;
    3. import org.apache.ibatis.annotations.Param;
    4. import java.util.List;
    5. /**
    6. * 用户映射器
    7. *
    8. * @author 大白菜
    9. * @date Created in 2022/7/24 14:53
    10. */
    11. public interface UserMapper {
    12. /**
    13. * 增
    14. * @return
    15. */
    16. int insertUser(User user);
    17. /**
    18. * 删
    19. * @return
    20. */
    21. int deleteUser(@Param("id") int id);
    22. /**
    23. * 改
    24. * @return
    25. */
    26. int updateUser(@Param("username") String userName,@Param("gender") String gender,@Param("id") int id);
    27. /**
    28. * 查
    29. * @return
    30. */
    31. User getUserById(@Param("id") int id);
    32. /**
    33. * 查多个
    34. */
    35. List getUserList();
    36. }

    UserMapper.xml

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.bcn.mybatis.mapper.UserMapper">
    6. <insert id ="insertUser">
    7. insert into t_user values (null,#{username},#{password},#{age},#{gender},#{email});
    8. insert>
    9. <delete id="deleteUser">
    10. delete from t_user where id=#{id}
    11. delete>
    12. <update id="updateUser">
    13. update t_user set username=#{username},gender=#{gender} where id=#{id}
    14. update>
    15. <select id="getUserById" resultType="User">
    16. select * from t_user where id= #{id}
    17. select>
    18. <select id="getUserList" resultType="User">
    19. select * from t_user
    20. select>
    21. mapper>

    test.java

    1. package com.bcn.mybatis;
    2. import com.bcn.mybatis.mapper.UserMapper;
    3. import com.bcn.mybatis.pojo.User;
    4. import com.bcn.mybatis.utils.SqlSessionUtil;
    5. import org.apache.ibatis.io.Resources;
    6. import org.apache.ibatis.session.SqlSession;
    7. import org.apache.ibatis.session.SqlSessionFactory;
    8. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    9. import org.junit.Test;
    10. import java.io.IOException;
    11. import java.io.InputStream;
    12. /**
    13. * @author 大白菜
    14. * @date Created in 2022/7/24 15:28
    15. */
    16. public class test {
    17. @Test
    18. public void testInserter() throws IOException {
    19. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    20. UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
    21. userMapper.insertUser(new User(null,"root","123456",18,"男","123@163.com"));
    22. sqlSession.commit();
    23. sqlSession.close();
    24. }
    25. @Test
    26. public void testDeleteUser() throws Exception {
    27. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    28. UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
    29. userMapper.deleteUser(5);
    30. sqlSession.commit();
    31. sqlSession.close();
    32. }
    33. @Test
    34. public void testUpdateUser() throws Exception {
    35. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    36. UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
    37. userMapper.updateUser("bcn","女",3);
    38. sqlSession.commit();
    39. sqlSession.close();
    40. }
    41. @Test
    42. public void testgetUserById() throws Exception {
    43. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    44. UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
    45. User user=userMapper.getUserById(3);
    46. System.out.println(user);
    47. sqlSession.commit();
    48. sqlSession.close();
    49. }
    50. @Test
    51. public void testgetUserList() throws Exception {
    52. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    53. UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
    54. userMapper.getUserList();
    55. sqlSession.commit();
    56. sqlSession.close();
    57. }
    58. }

    注意点

    1 查询标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射关系

    2 resultType:自动映射,用于属性名和表中字段名一致的情况

    3 resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况

    4 因为在核心配置文件里我们写过了pojo的映射,因此在这里不需要写上类地址全名,写类名即可

    2.5 Quary

    查询一个实体类对象

    1. /**
    2. * 根据用户id查询用户信息
    3. * @param id
    4. * @return
    5. */
    6. User getUserById(@Param("id") int id);
    1. <select id="getUserById" resultType="User">
    2. select * from t_user where id = #{id}
    3. select>

    查询一个list集合

    1. /**
    2. * 查询所有用户信息
    3. * @return
    4. */
    5. List getUserList();
    1. <select id="getUserList" resultType="User">
    2. select * from t_user
    3. select>

    查询单个数据

    1. /**
    2. * 查询用户的总记录数
    3. * @return
    4. * 在MyBatis中,对于Java中常用的类型都设置了类型别名
    5. * 例如: java.lang.Integer-->int|integer
    6. * 例如: int-->_int|_integer
    7. * 例如: Map-->map,List-->list
    8. */
    9. int getCount();
    1. <select id="getCount" resultType="_integer">
    2. select count(id) from t_user
    3. select>

    查询一条数据为map集合

    1. /**
    2. * 根据用户id查询用户信息为map集合
    3. * @param id
    4. * @return
    5. */
    6. Map getUserToMap(@Param("id") int id);
    1. <select id="getUserToMap" resultType="map">
    2. select * from t_user where id = #{id}
    3. select>

    查询多条数据为map的集合

    1. /**
    2. * 查询所有用户信息为map集合
    3. * @return
    4. * 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此
    5. 时可以将这些map放在一个list集合中获取
    6. */
    7. List> getAllUserToMap();
    1. <select id="getAllUserToMap" resultType="map">
    2. select * from t_user
    3. select>

    模糊查询

    1. /**
    2. * 测试模糊查询
    3. * @param mohu
    4. * @return
    5. */
    6. List testMohu(@Param("mohu") String mohu);
    1. <select id="testMohu" resultType="User">
    2. select * from t_user where username like "%"#{mohu}"%"
    3. select>

    2.6 Special SQL

    批量删除

    1. /**
    2. * 批量删除
    3. * @param ids
    4. * @return
    5. */
    6. int deleteMore(@Param("ids") String ids);
    1. <delete id="deleteMore">
    2. delete from t_user where id in (${ids})
    3. delete>
    1. @Test
    2. public void testDeleteMor() throws Exception {
    3. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    4. UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
    5. userMapper.deleteMore("2,3,4,5");
    6. sqlSession.commit();
    7. sqlSession.close();
    8. }

    注意

    1 所要删除对象表现不是用list或者map来表示,而是使用字符串的,格式如"1,2,3"

    2 参数使用方式得是${},因为#{}会默认加上 ' 从而导致最终查询失败

    动态设置表名

    1. /**
    2. * 动态设置表名,查询所有的用户信息
    3. * @param tableName
    4. * @return
    5. */
    6. List getAllUser(@Param("tableName") String tableName);
    1. <select id="getAllUser" resultType="User">
    2. select * from ${tableName}
    3. select>

    注意

    1 参数的表示只能是${},因为表名也是不能加单引号的

    添加功能获取自增的主键(重点知识)

    场景:在添加信息之后想获取它的主键

    具体做法:使用useGeneratedKeys和keyProperty

    1. /**
    2. * 添加用户信息
    3. * @param user
    4. * @return
    5. * useGeneratedKeys:设置使用自增的主键
    6. * keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
    7. */
    8. int insertUser(User user);
    1. <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    2. insert into t_user values(null,#{username},#{password},#{age},#{sex})
    3. insert>

    🔥2.7 Custom Map

    2.7.1 Custom setting

    当数据库中的字段名和实体类中的属性名不一致时,可以使用resultMap来实现自定义映射

    方式一

    使用resultMap来获取映射标签

    id映射标签的id
    type实体类对象
    id主键映射
    result普通键映射
    association多对一映射
    collection一对多映射
    property实体类属性名
    column数据库字段名
    1. <resultMap id="userMap" type="User">
    2. <id property="id" column="id">id>
    3. <result property="userName" column="user_name">result>
    4. <result property="password" column="password">result>
    5. <result property="age" column="age">result>
    6. <result property="sex" column="sex">result>
    7. resultMap>
    8. <select id="testMohu" resultMap="userMap">
    9. select * from t_user where username like '%${mohu}%'
    10. select>

    注意:

    1 传统的Sql语句中我们使用的是resultType,而这里使用的是resultMap

    方式二:

    Mysql中的字段名的格式要求是_,Java中属性名的格式要求是驼峰,命名都规范的话直接使用一个setting全局配置即可

    1. <settings>
    2. <setting name="mapUnderscoreToCamelCase" value="true"/>
    3. settings>

    2.7.2 Many to one 

    遇到多对一的i情况如何查询?比如说查询一个员工的全部信息和它公司的全部信息

    Employee实体类中的一个属性是Company对象,而不是Company的属性

    方式一:级联

    1. <resultMap id="EmpMap" type="User">
    2. <id property="empId" column="emp_id">id>
    3. ~
    4. <result property="company.comId" column="comp_id">result>
    5. <result property="company.comName" column="comp_name">result>
    6. resultMap>
    7. <select id="getEmpAndComByEmpId" resultMap="EmpMap">
    8. select emp.*,comp.*
    9. from emp
    10. left join comp
    11. on emp.comp_id=comp.emp_id
    12. where emp.emp_id=#{empId}
    13. select>

    方式二:association

    其实就是一个套娃,在resultMap里面再套上一个resultMap,只不过这里的resultMap换了名字叫做association

    property需要映射的属性名
    javaType该属性的类型
    1. <resultMap id="EmpMap" type="Emplyee">
    2. <id property="empId" column="emp_id">id>
    3. ~
    4. <association property="company" javaType="Company">
    5. <id property="comId" column="com_id">id>
    6. <result property="comName" column="com_name">result>
    7. association>
    8. resultMap>

    方式三:分布查询

    就是将一个Sql语句拆分为多个Sql语句

    Step1:查询员工的基本信息

    Employee getEmpByStep(@Param("empId") int empId)
    1. <resultMap id="EmpMapStepMap" type="Emplyee">
    2. <id property="empId" column="emp_id">id>
    3. ~
    4. <association property="company"
    5. select="com.bcn.mybatis.mapper.EmpMapper.getEmpAndCompByStepTwo"
    6. column="comp_id">
    7. association>
    8. resultMap>

    Step2:查询公司的基本信息

    Company getEmpCompByStep(@Param("compId") int compId);
    1. <select id="getEmpCompByStep" resultType="Company">
    2. select * from comp where compId = #{compId}
    3. select>

    2.7.3 One To Many

    查询一对多的数据,比如说查询一个公司的信息和它所有员工的信息

    Company对象的一个属性是 private List Emps

    方式一:collection

    Company getCompEmpByCompId(@Param("CompId") int CompId);
    1. <resultMap id="compEmpMap" type="Company">
    2. <id property="CompId" column="comp_id">id>
    3. ~
    4. <collection property="emps" ofType="Employee">
    5. <id property="empId" column="emp_id">id>
    6. ~
    7. collection>
    8. resultMap>
    9. <select id="getCompEmpByCompId" resultMap="compEmpMap">
    10. select comp.*,emp.*
    11. from comp
    12. left join emp
    13. on comp.compId=emp.compId
    14. where comp.compId=#{compId}
    15. select>

    方式二:分布查询

    Step1:查询公司信息

    Company getCompByStep(@Param("compId") int compId);
    1. <resultMap id="CompEmpStep" type="Company">
    2. <id> ~
    3. <collection property="emps" fetch="eager"
    4. select="com.bcn.Mybatis.mapper.EmpMapper.getEmpListByCompId" column="compId">
    5. collection>
    6. resultMap>
    7. <select id="getCompByStep" resultMap="CompEmpStep">
    8. select * from comp where comp_Id=#{compId}
    9. select>

    Sep2:查询所有员工信息

    List getEmpListByCompId(@param("compId") int CompId);
    1. <select id="getEmpListByCompId" resultType="Employee">
    2. select * from emp where empId=#{empId}
    3. select>

    2.7.4 Lazy loeading

     分布查询的优点是能够实现延迟加载(懒加载),简单的说就是分布是有多个Sql语句的,我想使用员工信息的时候它才会它,我想使用公司信息的时候它才会加载它。这样的按需加载就可以灵活的使用系统资源。

    比如下面的例子,虽然我们中间有很多的Sql语句,但是我们最终使用到的就是员工的名字,因此它只会执行查找员工信息的语句

    1. @Test
    2. public void testGetEmpAndCompByStep() throws Exception {
    3. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    4. EmpMapper EmpMapper =sqlSession.getMapper(EmpMapper.class);
    5. Employee emp=EmpMapper.getEmpAndCompByStepOne(2);
    6. System.out.println(emp.getEmpName());
    7. sqlSession.commit();
    8. sqlSession.close();
    9. }

    做法:在mybatis-config.xml核心配置文件中配置全局配置信息

    lazyLoadingEnabled全局是否开启延迟加载
    aggressiveLazyLoading全局是否强制关闭延迟加载
    fetchType局部分布查询中是否同意延迟加载 eager or lazy
    1. <settings>
    2. <setting name="lazyLoadingEnabled" value="true"/>
    3. <setting name="aggressiveLazyLoading" value="false"/>
    4. settings>
    1. <association property="company" fetchType="eager"
    2. ~
    3. association>

    2.8 Dynamic Sql

    解决复杂Sql查询,来进行动态拼装Sql语句的功能,本质就是映射中的各种标签

    2.8.1 if、where

    if是通过test中的表达式来判断标签中的信息是否有效,有效则拼接到sql中

    例:若输入的员工信息全部是非空的,则把他给找出来

    where常和if一起使用

    a) 若where中有标签成立,则自动生成where关键字,且会将多余的and去掉

    b) 若a不成立,则无where

    1. package com.bcn.mybatis.mapper;
    2. import com.bcn.mybatis.pojo.Employee;
    3. import java.util.List;
    4. /**
    5. * @author 大白菜
    6. * @date Created in 2022/7/29 21:04
    7. */
    8. public interface EmployeeMapper {
    9. List getEmployeeListByCondition(Employee employee);
    10. }
    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.bcn.mybatis.mapper.EmployeeMapper">
    6. <select id="getEmployeeListByCondition" resultType="com.bcn.mybatis.pojo.Employee">
    7. select * from t_employee
    8. <where>
    9. <if test="name != null and name != '' ">
    10. and name = #{name}
    11. if>
    12. <if test="age != null and age != '' ">
    13. and age = #{age}
    14. if>
    15. <if test="sex != null and sex != '' ">
    16. and sex = #{sex}
    17. if>
    18. where>
    19. select>
    20. mapper>
    1. package com.bcn.mybatis;
    2. import com.bcn.mybatis.mapper.EmployeeMapper;
    3. import com.bcn.mybatis.pojo.Employee;
    4. import com.bcn.mybatis.utils.SqlSessionUtil;
    5. import org.apache.ibatis.session.SqlSession;
    6. import org.junit.Test;
    7. import java.io.IOException;
    8. import java.util.List;
    9. /**
    10. * @author 大白菜
    11. * @date Created in 2022/7/29 21:12
    12. */
    13. public class EmployeeTest {
    14. @Test
    15. public void testInserter() throws IOException {
    16. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    17. EmployeeMapper EmployeeMapper =sqlSession.getMapper(EmployeeMapper.class);
    18. Employee employee=new Employee(null,"张三", 18,"男");
    19. List list=EmployeeMapper.getEmployeeListByCondition(employee);
    20. list.forEach(System.out::println);
    21. sqlSession.commit();
    22. sqlSession.close();
    23. }
    24. }

    2.8.2 trim

    有时候我们的and加在后面,where处理不了,就需要用到trim了

    prefix、suffix:在标签的前面或后面添加指定内容

    prefexOverrides、suffixOverrides:在标签的前面或后面删除指定内容

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.bcn.mybatis.mapper.EmployeeMapper">
    6. <select id="getEmployeeListByCondition" resultType="com.bcn.mybatis.pojo.Employee">
    7. select * from t_employee
    8. <trim prefix="where" suffixOverrides="and">
    9. <if test="name != null and name != '' ">
    10. name = #{name} and
    11. if>
    12. <if test="age != null and age != '' ">
    13. age = #{age} and
    14. if>
    15. <if test="sex != null and sex != '' ">
    16. sex = #{sex} and
    17. if>
    18. trim>
    19. select>
    20. mapper>

    🔥2.8.3 foreach

    批量操作,比如添加、删除多个用户

    collection列表
    item每个列表中的元素
    separator分隔符
    1. <insert id="insertMoreEmployees">
    2. insert into t_employee values
    3. <foreach collection="employees" item="employee" separator=",">
    4. (null,#{employee.name},#{employee.age},#{employee.sex})
    5. foreach>
    6. insert>
    7. <delete id="deleteMoreByArray">
    8. delete from t_employees where
    9. <foreach collection="ids" item="is" separator="or">
    10. eid=#{eid}
    11. foreach>
    12. delete>

    2.8.4 SQL 

    有时候我们想反复的用到sql语句,那么就可以将其封装成一个sql片段,从而提高代码的复用性

    2.9 Cache

    2.9.1 L1 Cache

    Mybatis中的缓存主要针对查询

    L1即1级缓存,L1是SqlSession级别的(可以理解为对象级别),通过同一个(如同一个sqlsession1)SqlSession查询的数据会被缓存下来,下次查询的时候也会先从缓存中进行查询。默认自动开启

    L1失效(不能从Cache中查询,需要从Database中查询)主要有以下几种情况

    • 同一个SqlSession,查询条件不同
    • ~,两次查询之间出现了增删改
    • ~,两次查询之间手动清空缓存

    💧2.9.2 L2 Chche

    L2,即2级缓存,L2是SqlSessionFactory级别的(可以理解为类级别),通过同一个(如sqlsession1和sqlsession2)SqlSessionFactory查询的数据被缓存,下次查询会先从L2中查询。开启的条件必须满足以下四个条件

    • 核心配置文件中,使用cacheEnabled="true"
    • xml映射文件中加一行
    • 每次SqlSession对象操作完之后进行关闭和提交
    • 查询的实体对象加上 implements Serializable

    每次执行完之后会有一个Cache Hit Ratio缓存命中率的信息,只要不是0就是查询成功啦

    失效的条件:两次查询之间执行了增删改

    💧2.9.3 Cache query policy

    • 类似于OS中的MMU内存管理单元机制,L2就是TLB快表
    • 程序首先查询的是L2,如果L2没有命中则查询L1,若还是没有命中则查询数据库
    • SqlSession关闭之后,L1中的数据才会写入到L2中
    • 只有L2可以使用第三方缓存如EHCache,有需要可以配置

    🔥2.10 Reverse Engineering

    RE逆向工程,即代码生成器,即你在开始一个新的项目的时候,它可以帮你自动生成如Mapper、Pojo之类的包和对象,减少一点的开发时间吧

    网上有很多说用mybatis-generator-maven-plugin之类的插件,经过笔者测试使用MybatisX最好

    使用方法

    1 数据库建表

      2 创建一个新的工程,连接到数据库

     3 选择MybatisX-Generator

     4 按照以下配置

     5 查看最终结果,MybatisX逆向工程创建成功,而且xml文件中自动帮我们建好了一个Map

     2.11 Paging

    分页即如图所示,具体做法是使用分页查询的一个插件,在每次查询功能之前开启PageHelper.startPage(int pageNum, int pageSize)

    pageNum:总页面数

    pageSize:每页记录的条数

    依赖

    1. <dependency>
    2. <groupId>com.github.pagehelpergroupId>
    3. <artifactId>pagehelperartifactId>
    4. <version>5.3.0version>
    5. dependency>

    在config-xml文件中配置分页插件

    1. <plugins>
    2. <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
    3. plugins>

    getUserList函数

    1. <select id="getUserList" resultType="User">
    2. select * from t_user
    3. select>

    测试类

    1. @Test
    2. public void testPage(){
    3. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    4. UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
    5. //查询功能之前开启分页功能
    6. PageHelper.startPage(1,3);
    7. List users=userMapper.getUserList();
    8. users.forEach(System.out::println);
    9. }

    运行结果

     如果想获取分页的所有数据也可以

    1. @Test
    2. public void testPage(){
    3. SqlSession sqlSession= SqlSessionUtil.getSqlSession();
    4. UserMapper userMapper =sqlSession.getMapper(UserMapper.class);
    5. //查询功能之前开启分页功能
    6. Page page=PageHelper.startPage(1,3);
    7. List users=userMapper.getUserList();
    8. //查询功能之后可以获取分页相关的所有数据
    9. PageInfo pageInfo = new PageInfo<>(users,5);
    10. users.forEach(System.out::println);
    11. System.out.println(page);
    12. }
    1. Page{count=true, pageNum=1, pageSize=3,
    2. startRow=0, endRow=3, total=7, pages=3, reasonable=false, pageSizeZero=false}
    3. [User(id=3, username=bcn, password=123456, age=23, gender=女, email=123@163.com),
    4. User(id=4, username=admin, password=123456, age=23, gender=男, email=123@163.com),
    5. User(id=6, username=admin, password=123456, age=23, gender=男, email=123@163.com)]

    三、Spring--轻量级Java开发框架

    3.1 Introduction

    使用其核心思想IOC管理组件,使用AOP思想实现功能增强。

    Spring全家桶

    SpringFrameworkSpring系列的核心,业务层框架,所有的项目都需要依赖于SpringFramework
    SpringMVCWeb层框架
    SpringBoot基于Spring的脚手架,简化了SpringFramework和SpringMvc,可理解升级版Spring
    SpringCloud微服务,将大型单个拆分成多个组件

    3.2 Spring Framework

    3.2.1 properties

    SpringFramework有以下特性

    • 非侵入式:使用 Spring Framework 开发应用程序时,Spring 对应用程序本身的结构影响非常 小。对领域模型可以做到零污染;对功能性组件也只需要使用几个简单的注解进行标记,完全不会破坏原有结构,反而能将组件结构进一步简化。这就使得基于 Spring Framework 开发应用程序时结构清晰、简洁优雅。
    • 控制反转:IOC——Inversion of Control,翻转资源获取方向。把自己创建资源、向环境索取资源变成环境将资源准备好,我们享受资源注入。
    • 面向切面编程:AOP——Aspect Oriented Programming,在不修改源代码的基础上增强代码功能。
    • 容器:Spring IOC 是一个容器,因为它包含并且管理组件对象的生命周期。组件享受到了容器化的管理,替程序员屏蔽了组件创建过程中的大量细节,极大的降低了使用门槛,大幅度提高了开发效率。
    • 组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用 XML 和 Java 注解组合这些对象。这使得我们可以基于一个个功能明确、边界清晰的组件有条不紊的搭建超大型复杂应用系统。
    • 声明式:很多以前需要编写代码才能实现的功能,现在只需要声明需求即可由框架代为实现。
    • 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库。而且 Spring 旗下的项目已经覆盖了广泛领域,很多方面的功能性需求可以在 Spring Framework 的基础上全部使用 Spring 来实现。

    3.2.2 Five functional modules

    Core Container

    核心容器,在Spring环境下使用任何功能都必须基于IOC容器
    AOP&Aspects面向切面编程
    TestingJunit或TestNG测试框架

    Data Access/Integration

    提供对数据访问/集成的功能
    Spring MVC提供面向Web程序的集成功能

    🔥 3.3 IOC 

    3.3.1 Ideology

    IOC:Inversion of Control反转控制,是一种资源获取的方式,简单的理解为之前所有的资源都需要自己创建,现在是Spring为我们提供啥我们就用啥,不必关心资源是如何创建的

    DI:Dependency Injection依赖注入,是IOC的具体实现方式,具体来说A依赖对象B,那么就会对B进行赋值

    3.3.2 Achieve

    针对IOC思想,Spring中有一个专门的容器就叫做IOC容器,该容器中的管理的组件叫做Bean。注意,在创建bean之前一定是需要创建IOC容器。IOC容器的两种实现方式如下

    • BeanFactory:Spring内部使用,不提供给开发者使用
    • ApplicationContext:BeanFactory的子接口,有更多的特性。提供给开发者使用,开发中都需要用到这个

    主要的实现类:搜索BeanFactory,再按ctrl+H

    类名介绍
    WebApplicationContext如果是Java工程,则叫做ApplicationContext,如果是Web工程,则叫做WebApplicationContext。该类将对象引入存储于ServletContext域中
    ConfigurableApplicationContextApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、 关闭和刷新上下文的能力。
    FileSystemXmlApplicationContext通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象
    ClassPathXmlApplicationContext通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象

    3.4 Bean

    3.4.1 Tag and Scan

    Bean主要可以通过XML和注解来管理,XML管理会非常的复杂,在实战中使用的比较少,一般都是使用注解来管理

    注解:以@为标志符Tag,其主要是一个标记,当框架扫描Scan注解,就会按照注解的功能来具体执行

    关键注解

    名称作用
    @Component将类标志为普通组件,只要类中有了这个组件之后,就可以被IOC容器所管理
    @Controller将类标识为控制层组件
    @Service将类标识为业务层组件
    @Repository将类表示为持久层组件
    @mapper是Myabtis的注解,并非是Spring 的,所以用到Mybatis的时候才用它

    联系:阅读源码后,我们发现@Controller,@Service和@Repositort都只是在@Component的基础上新起另一个名字,所以从IOC容器管理的角度看,这三个本质上无区别,只是让程序员看的更加清楚一点。

    使用xml管理bean的时候,每个bean都有一个唯一的标志符,使用注解的时候每个bean也会有一个唯一的标志符,如UserController对应的bean就是userController,当然我们也可以自定义bean的id,方法如下

    具体实现步骤如下

    1. 创建各个对象,并给各个对象加上注释

    2.创建spring的xml文件,并向其中添加扫描组件

    exclude-filter不扫描某个组件,因为在整合Spring和SpirngMVC中,SpringMVC主要负责Controller层组件,而Spring负责除Controller层组件之外的所有组件
    include-filter只扫描某个组件
    type:"annotation"根据注解类型来进行排除
    experssion组件的名称,需要填写注解全类名,可由以下操作来进行获取

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    6. <context:component-scan base-package="com.bcn.spring">context:component-scan>
    7. beans>

    3. 测试 

    1. public class IOCByAnnotationTest {
    2. @Test
    3. public void test(){
    4. //获取配置文件
    5. ApplicationContext ioc=new ClassPathXmlApplicationContext("spring-ioc-annotation.xml");
    6. //获取Bean对象
    7. UserController userController=ioc.getBean(UserController.class);
    8. UserService userService=ioc.getBean(UserService.class);
    9. UserMapper userMapper=ioc.getBean(UserMapper.class);
    10. System.out.println(userController);
    11. System.out.println(userService);
    12. System.out.println(userMapper);
    13. }
    14. }

     4. 测试结果

    四、SpringMVC

    接受浏览器发送的请求,并响应浏览器数据

    五、整合

  • 相关阅读:
    个人如何选择主观交易还是程序化交易接口?
    将文件上传到阿里云OSS详细步骤
    训练记录day13 (想起来今天还没发博客
    数据结构与算法C语言版学习笔记(2)-线性表、顺序存储结构的线性表
    SpringCloud - Spring Cloud Alibaba 之 Seata分布式事务服务详解;部署(十八)
    2023年中国产业互联网行业交易规模及发展前景分析:产业互联网价值快速显现,发展潜力将进一步释放[图]
    【Hive-Exception】return code 1 from org.apache.hadoop.hive.ql.exec.DDLTaskHIVE
    es6 函数的使用
    el-tooltip在el-table-column的使用
    自动驾驶相关
  • 原文地址:https://blog.csdn.net/ccaoshangfei/article/details/126805162