SSM(Spring+SpringMVC+Mybatis)框架

Mybatis篇常见知识点(面试题在文章最后)

1.jdbc的缺点以及mybatis的优点,jdbc问题的解决思路

  • JDBC

    • 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能

    • Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变 java代码

    • 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护

    • 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便

 MyBatis

  • 轻量级,性能出色

  • SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据

  • 开发效率稍逊于HIbernate,但是完全能够接受

JDBC问题解决思路

①使用数据库连接池初始化连接资源

②将sql语句抽取到xml配置文件中

③使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射

2.mybatis的核心配置文件 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
     PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!--
         MyBatis核心配置文件中,标签的顺序:
         properties?,settings?,typeAliases?,typeHandlers?,
         objectFactory?,objectWrapperFactory?,reflectorFactory?,
         plugins?,environments?,databaseIdProvider?,mappers?
	-->
	<!--引入properties文件-->
	<properties resource="jdbc.properties" />
	<!--设置类型别名-->
	<typeAliases>
	<!--
		typeAlias:设置某个类型的别名
		属性:
			type:设置需要设置别名的类型
			alias:设置某个类型的别名,若不设置该属性,那么该类型拥有默认的别名,即类名且不区分大小写
	-->
		<!--<typeAlias type="com.xxx.pojo.User"></typeAlias>-->
		<!--以包为单位,将包下所有的类型设置默认的类型别名,即类名且不区分大小写-->
		<package name="com.xxx.pojo"/>
	</typeAliases>
	<!--
		environments:配置多个连接数据库的环境
		属性:
			default:设置默认使用的环境的id
	-->
	<environments default="development">
 <!--
		environment:配置某个具体的环境
		属性:
			id:表示连接数据库的环境的唯一标识,不能重复
	-->
	<environment id="development">
		<!--
			transactionManager:设置事务管理方式
			属性:
				type="JDBC|MANAGED"
				JDBC:表示当前环境中,执行SQL时,使用的是JDBC中原生的事务管理方式,事务的提交或回滚需要手动处理
				MANAGED:被管理,例如Spring
		-->
			<transactionManager type="JDBC"/>
			<!--
				dataSource:配置数据源
				属性:
              type:设置数据源的类型
              type="POOLED|UNPOOLED|JNDI"
                 POOLED:表示使用数据库连接池缓存数据库连接
                 UNPOOLED:表示不使用数据库连接池
                 JNDI:表示使用上下文中的数据源
			-->
				<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>
			<environment id="test">
          <transactionManager type="JDBC"/>
          <dataSource type="POOLED">
             <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
             <property name="url"value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"/>
             <property name="username" value="root"/>
             <property name="password" value="123456"/>
			</dataSource>
		</environment>
	</environments>
	<!--引入映射文件-->
	<mappers>
	<!--<mapper resource="mappers/UserMapper.xml"/>-->
	<!--
      以包为单位引入映射文件
         要求:
         1、mapper接口所在的包要和映射文件所在的包一致
         2、mapper接口要和映射文件的名字一致
	-->
		<package name="com.xxx.mapper"/>
	</mappers>
</configuration>

3.mybatis中的动态sql 

此处只写常用的,其他自己参考资料

3.1.动态模糊查询

/**
* 测试模糊查询
* @param name 
* 改注解可以对参数起别名与sql语句中#{保持一致}(一般在多参数下使用,否则会默认使用命名 
* param0,param1或者arr0,arr1)
* @return
* 注解的方式书写模糊查询语句,xml文件的方式书写动态sql
*/

@Select("select * from t_user where username like concat('%',#{username},'%')")
//@Select("select * from t_user where username like '%${username}%'")
List<User> selectAll(@Param("username") String username);

    <select id="selectAll" resultType="com.xxx.pojo.User">
        select * from t_user
        <where>
        <!--  if中test做属性值判断 字符串一下判断方式,Integer类型判断是否为null就可  -->
            <if test="username !=null and username !='' ">
                username like concat ('%',#{username},'%')
            </if>
        </where>
    </select>

 3.2.批量删除以及设置表名

  一定要用${},不可以用#{}

  1. ${}占位符:${}占位符会直接将参数的值拼接到SQL语句中,相当于字符串的替换。这意味着在使用${}时,参数的值将直接嵌入到SQL语句中,可能会导致SQL注入的风险。因此,${}主要适用于对静态、不包含用户输入的参数进行替换。

  2. #{}占位符:#{}占位符会使用预编译的方式,将参数的值放在SQL语句中的占位符位置,并使用JDBC的PreparedStatement进行参数注入。这样可以避免SQL注入的风险,并且能够处理参数的类型转换和特殊字符的转义,提高了应用的安全性和可靠性。因此,#{}主要适用于动态、包含用户输入的参数。

  3. 在 MyBatis 中,使用 ${} 来处理批量删除和设置表名是因为 ${} 是进行字符串替换的占位符,它会直接将参数的值插入到 SQL 语句中。这在某些情况下是必需的,因为 #{} 是使用预编译的方式来处理参数的占位符,会自动进行参数值的转义和类型处理,而批量删除和设置表名这两个场景通常需要使用动态的字符串。

 4 分步查询

  不做过多解释,直接看代码(mybatis视频质料可取b站看尚硅谷的)

多对一

 一对多

 5.mybatis注解开发  不做解释与示例

 一对多 多对一 多对多推荐使用xml文件

6.Mybatis中一级缓存和二级缓存

https://blog.csdn.net/zy_zhangruichen/article/details/122592504

缓存的意义是将用户经常查询的数据放入缓存(内存)中去,用户去查询数据的时候就不需要从磁盘(关系型数据库)中查询,直接从缓存中查询,从而提高了查询效率,解决了高并发中系统的性能问题。Mybatis中提供一级缓存与二级缓存。

一级缓存

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问

使一级缓存失效的四种情况:

1) 不同的SqlSession对应不同的一级缓存

2) 同一个SqlSession但是查询条件不同

3) 同一个SqlSession两次查询期间执行了任何一次增删改操作

4) 同一个SqlSession两次查询期间手动清空了缓存

二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被

缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件:

a>在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置

b>在映射文件中设置标签<cache/>

c>二级缓存必须在SqlSession关闭或提交之后有效

d>查询的数据所转换的实体类类型必须实现序列化的接口

使二级缓存失效的情况:

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

二级缓存的相关配置

在mapper配置文件中添加的cache标签可以设置一些属性:

①eviction属性:缓存回收策略,默认的是 LRU。

LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。

FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。

SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

②flushInterval属性:刷新间隔,单位毫秒

默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

③size属性:引用数目,正整数

代表缓存最多可以存储多少个对象,太大容易导致内存溢出

④readOnly属性:只读, true/false

true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了 很重要的性能优势。

false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是

false。

MyBatis缓存查询的顺序

先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。

如果二级缓存没有命中,再查询一级缓存

如果一级缓存也没有命中,则查询数据库

SqlSession关闭之后,一级缓存中的数据会写入二级缓存

7.MyBatis的逆向工程

  

<?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>
    <!-- 引入配置文件 数据库连接信息 -->
<!--    <properties resource="jdbc.properties"/>-->
    <!-- 指定连接数据库的JDBC驱动包所在位置,指定到你本机的完整路径 -->
<!--    <classPathEntry location="src/main/resources/mysql-connector-java-8.0.26.jar"/>-->

    <!-- 配置table表信息内容体,targetRuntime指定采用MyBatis3的版本 -->
    <context id="context" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自动生成的注释,由于生成的注释都是英文的,可以不让它生成.  true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
            <!--去除timestamp -->
            <property name="suppressDate" value="true"/>
        </commentGenerator>

        <!-- 配置数据库连接信息 connectionFactory与jdbcConnection只能配置其一-->
        <!-- 数据库的相关配置  mysql8: com.mysql.cj.jdbc.Driver-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/crm?serverTimezone=UTC"
                        userId="root"
                        password="root"/>

        <!-- 配置数据库连接信息 -->
        <!-- <connectionFactory>
             <property name="driverClass" value="${jdbc.driver}"/>
             <property name="connectionURL" value="${jdbc.url}"/>
             <property name="userId" value="${jdbc.username}"/>
             <property name="password" value="${jdbc.password}"/>
         </connectionFactory>-->



        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- 实体类生成的位置 -->
        <javaModelGenerator targetPackage="com.xxx.pojo" targetProject="src/main/java">
            <property name="enableSubPackages" value="false"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- *Mapper.xml 文件的位置 ,targetPackage:包名,targetProject:项目下的路径-->
        <sqlMapGenerator targetPackage="com.xxx.mapper" targetProject="src/main/resources">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- Mapper 接口文件的位置 -->
        <javaClientGenerator targetPackage="com.xxx.mapper" targetProject="src/main/java" type="XMLMAPPER">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <!-- 配置表信息 -->
        <table tableName="t_customer_serve" domainObjectName="CustomerServe">
            <!--是否生成有参的构造方法, 默认否-->
            <property name="constructorBased" value="false"/>
            <!--默认值为false,如果为true,在生成的sql语句中表名中不会加上catalog或schema-->
            <property name="ignoreQualifiersAtRuntime" value="false"/>
            <!--默认值为false,如果为true创建不可变类,生成包含所有field参数的构造方法,没有setter方法-->
            <property name="immutable" value="false"/>
            <!--是否只生成模型类,默认值为false-->
            <property name="modelOnly" value="false"/>
            <!--是否使用真实的字段名称作为类中的属性名称,默认值为false-->
            <property name="useActualColumnNames" value="false"/>
            <!--主键生成策略:可选值:MySql、SqlServer、SYBASE、DB2、Derby等
                使用MySql即生成:SELECT LAST_INSERT_ID() 获取主键值
            -->
            <generatedKey column="id" sqlStatement="MySql"/>
        </table>

  <!--  数据库中多个表 可以对table标签中的内容进行复制,修改标签中tableName和domainObjectName属性值即可-->
      
    </context>
</generatorConfiguration>

pom坐标

<!-- 依赖MyBatis核心包 -->
<dependencies>
	<dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
	</dependency>
	<!-- junit测试 -->
	<dependency>
	<groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
	</dependency>
	<!-- log4j日志 -->
	<dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
	</dependency>
	<dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
	</dependency>
</dependencies>
<!-- 控制Maven在构建过程中相关配置 -->
<build>
	<!-- 构建过程中用到的插件 -->
	<plugins>
		<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
		<plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.0</version>
			<!-- 插件的依赖 -->
			<dependencies>
				<!-- 逆向工程的核心依赖 -->
				<dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.3.2</version>
				</dependency>
				<!-- MySQL驱动 -->
				<dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>8.0.16</version>
				</dependency>
			</dependencies>
		</plugin>
	</plugins>
</build>

8.mybatis的分页查询

分页基础知识点

limit index,pageSize

pageSize:每页显示的条数

pageNum:当前页的页码

index:当前页的起始索引,index=(pageNum-1)*pageSize

count:总记录数

totalPage:总页数

totalPage = count / pageSize;

if(count % pageSize != 0){

totalPage += 1;

}

pageSize=4,pageNum=1,index=0 limit 0,4

pageSize=4,pageNum=3,index=8 limit 8,4

pageSize=4,pageNum=6,index=20 limit 8,4

分页查询主要步骤

导入依赖坐标

<properties> 
     <pagehelper.version>5.1.2</pagehelper.version>
</properties>

<dependencies>

<!--mybatis分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>${pagehelper.version}</version>
        </dependency>
</dependencies>

部分主要代码演示

/**
*   PageData<T>编写的分页数据统一封装类 类似于模板思想
*   UserQuery 就是实体类 只是简化了所需(表)字段(实体类属性)
*   PageHelper.startPage:(pageNum,pageSize 去基础知识点看不理解的) 
*   public static <E> Page<E> startPage(int pageNum, int pageSize) {
*        return startPage(pageNum, pageSize, true);
*    }
*
*   PageInfo 可去查看源码,类中属性大体就是基础知识点中的东西(仅展示部分属性)
*
*
*/ 

    public PageData getAllPageSaleChance(UserQuery userQuery) {
         //开启分页查询
        PageHelper.startPage(userQuery.getPage(), userQuery.getLimit());
        //条件查询
        List<User> users = userMapper.selectByUserQuery(userQuery);
        //封装分页数据
        PageInfo<User> pageInfo = new PageInfo(users);
        return PageData.data(pageInfo.getList(), pageInfo.getTotal());
    }

总结

a>在查询功能之前使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能

pageNum:当前页的页码

pageSize:每页显示的条数

b>在查询获取list集合之后,使用PageInfo<T> pageInfo = new PageInfo<>(List<T> list, int

navigatePages)获取分页相关数据

list:分页之后的数据

navigatePages:导航分页的页码数

c>分页相关数据

PageInfo{

pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8,

list=Page{count=true, pageNum=8, pageSize=4, startRow=28, endRow=32, total=30,

pages=8, reasonable=false, pageSizeZero=false},

prePage=7, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true,

hasNextPage=false, navigatePages=5, navigateFirstPage4, navigateLastPage8,

navigatepageNums=[4, 5, 6, 7, 8]

}

pageNum:当前页的页码

pageSize:每页显示的条数

size:当前页显示的真实条数

total:总记录数

pages:总页数

prePage:上一页的页码

nextPage:下一页的页码

isFirstPage/isLastPage:是否为第一页/最后一页

hasPreviousPage/hasNextPage:是否存在上一页/下一页

navigatePages:导航分页的页码数

navigatepageNums:导航分页的页码,[1,2,3,4,5]

在后续springBoot中利用MybatisPlus更容易实现分页数据以及和分页绑定的查询功能(后续springboot大体总结中会详细提到),这里展示代码部分

/**
	 * 分页查询
	 *
	 */
	@Test
	void testPage() {

		IPage page = new Page(1, 5);
		uSerDao.selectPage(page, null);

		System.out.println(page.getCurrent()); //当前页
		System.out.println(page.getSize());    //每页展示数据条数
		System.out.println(page.getPages());   //多少页
		System.out.println(page.getTotal());   //数据总数(表中数据总数,
		                               // 不是分页后的数据总数不要搞混)
		System.out.println(page.getRecords()); //分页数据存放
	}

 面试题

 

mybatis延迟加载的原理是什么

mybatis延迟加载一般仅在联合查询时(不懂的可以去看上面多表查询)在association关联对象(一对一、多对一)和collection关联集合对象(一对多,多对多 表之间的关系不在做叙述)中使用。

在mybatis的配置文件中可以根据标签中的属性来配置是否开启延迟加载lazyLoadingEnable=true|false

原理:使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器intercept()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用,以上就是延迟加载的基本原理。

什么是MyBatis?它的特点是什么?

MyBatis是一个开源的持久层框架,它提供了许多功能和特性来简化与数据库的交互。它将SQL语句与Java代码分离,通过配置文件实现数据库操作,从而降低了开发人员处理数据库的复杂性。

MyBatis的特点包括:

1. 简化数据库操作:MyBatis使用简单的接口和SQL映射文件,将Java对象与数据库表进行映射,开发人员无需手动编写JDBC代码,简化了数据库操作的过程。

2. 灵活的SQL编写:MyBatis支持原生的SQL编写,允许开发人员自由编写SQL语句,可灵活控制数据查询和更新的过程。同时,MyBatis还提供了动态SQL的功能,可以根据条件动态生成SQL语句,提高了SQL的灵活性和重用性。

3. 强大的结果映射:MyBatis提供了强大的结果映射功能,可以将查询结果自动映射到Java对象或集合中,大大简化了结果获取和封装的过程。

4. 缓存支持:MyBatis具有一级缓存和二级缓存的支持。一级缓存是默认开启的,它保存了在同一次会话中执行的SQL语句的结果,避免了重复查询。而二级缓存是跨会话的缓存,可以提高相同查询的性能。

5. 与多种数据库兼容:MyBatis支持多种主流数据库,如MySQL、Oracle、SQL Server等,并提供了相应的数据库方言,允许开发人员在不同的数据库平台中无缝切换。

6. 易于集成:MyBatis可以与Spring、Spring Boot等框架集成,通过注解或XML配置,实现与其他框架的无缝集成,提供更便捷的开发和部署方式。

总之,MyBatis通过简化数据库操作、提供灵活的SQL编写、强大的结果映射、缓存支持和集成性等特点,使得开发人员可以更高效地进行数据库交互,提高了开发效率和应用性能。

MyBatis的工作原理是什么?

MyBatis的工作原理可以简单概括为以下几个步骤:

1. 读取配置文件:MyBatis的配置文件(通常命名为`mybatis-config.xml`)包含了框架的全局配置信息,包括数据库连接、缓存配置、映射器配置等。MyBatis在启动时会读取配置文件,并创建全局唯一的SqlSessionFactory对象。

2. 创建SqlSessionFactory:SqlSessionFactory是MyBatis的核心对象,它负责创建SqlSession对象。SqlSessionFactory使用配置文件中的信息,通过构建者模式创建SqlSession对象所需的数据库连接池、缓存等资源。

3. 创建SqlSession:SqlSession是MyBatis与数据库交互的主要对象,它封装了对数据库的操作方法。通过SqlSessionFactory的openSession方法,可以创建SqlSession对象。

4. 加载映射器配置:映射器配置是MyBatis的关键部分,它负责定义Java对象和数据库表之间的映射关系。MyBatis会根据配置文件中的映射器配置,加载映射器接口和对应的映射文件(通常命名为`xxxMapper.xml`),建立Java对象与数据库操作语句的映射关系。

5. 执行数据库操作:通过SqlSession对象调用映射器接口中定义的方法,将操作请求转化为SQL语句,并通过JDBC发送给数据库执行。MyBatis提供了丰富的API和注解来编写SQL语句,开发人员可以根据需求选择合适的方式。

6. 处理结果集:数据库执行完SQL语句后,MyBatis将结果集封装为Java对象或集合,并返回给调用方。MyBatis提供了强大的结果映射功能,可以自动将结果集映射到对象中,简化了结果处理的过程。

7. 关闭资源:在使用完毕后,需要关闭SqlSession对象和相关资源,以释放连接和避免资源泄漏。可以通过调用SqlSession的close方法来关闭会话。

通过以上步骤,MyBatis实现了Java对象与数据库表的映射、SQL语句的生成和执行、结果集的处理等数据库操作的工作。该工作原理具有灵活性和易用性,使得开发人员可以方便地进行数据库交互。

MyBatis的一级缓存和二级缓存有什么区别?如何配置缓存?

MyBatis的一级缓存(Local Cache)和二级缓存(Global Cache)是两种不同级别的缓存机制。

一级缓存:

- 一级缓存是默认开启的,它是SqlSession级别的缓存,只在同一个SqlSession内有效。

- 当执行相同的查询时,MyBatis会首先检查一级缓存中是否有对应的结果。如果有,则直接从缓存中获取结果,而不需要再次查询数据库。

- 一级缓存是由SqlSession维护的,当SqlSession被关闭或提交事务时,一级缓存将失效。

二级缓存:

- 二级缓存是SessionFactory级别的缓存,可以被多个SqlSession共享。

- 当执行查询操作时,如果一级缓存中没有对应的结果,MyBatis会查询二级缓存,如果找到相应的结果,则直接从缓存中获取。

- 二级缓存通过配置文件中的`<cache>`元素进行配置,可以配置Cache的实现类、缓存策略、过期时间等。

- 默认情况下,二级缓存是不开启的,需要手动配置开启,并且需要在映射文件中明确标注开启二级缓存。

配置缓存:

要配置缓存,在MyBatis的配置文件(通常是`mybatis-config.xml`)中,可以使用`<cache>`元素来配置缓存。

1. 开启一级缓存:一级缓存是默认开启的,无需额外配置。

2. 开启二级缓存:

   - 在`<cache>`元素中设置`enabled`属性为`true`表示开启二级缓存。

   - 可以选择不同的缓存实现类,默认提供了多种实现,如`org.apache.ibatis.cache.impl.PerpetualCache`和`org.mybatis.caches.ehcache.EhcacheCache`等。

   - 可以设置缓存的其他属性,如缓存策略(例如`FIFO`、`LRU`、`SOFT`、`WEAK`等)、过期时间等。

示例配置:
```xml
<!-- 在mybatis-config.xml中配置 -->
<configuration>
  <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  <!-- 或者使用默认的PerpetualCache -->
  <!-- <cache type="org.apache.ibatis.cache.impl.PerpetualCache"/> -->
</configuration>

<!-- 在映射文件中标注启用二级缓存 -->
<mapper namespace="com.example.mapper.UserMapper" >
  <cache/>
</mapper>
```

需要注意的是,缓存的使用需要慎重考虑,特别是在修改、删除、插入操作频繁的场景下。配置缓存时,需根据实际情况权衡缓存的使用,避免出现脏数据或缓存滥用导致的性能问题。

MyBatis中的延迟加载是什么?如何使用延迟加载?

在MyBatis中,延迟加载(Lazy Loading)是一种优化技术,它允许在需要时才加载关联对象的数据,减少数据库查询的数量,提高查询效率。

延迟加载的基本原理是:当访问一个对象关联字段时,不立即查询数据库获取关联对象的数据,而是生成一个代理对象并返回。只有当真正使用关联对象的数据时,才会触发数据库查询。

使用延迟加载需要注意以下几点:

1. 配置关联对象的延迟加载:在映射文件中,可以使用`<association>`(一对一关联)和`<collection>`(一对多关联)元素的`fetchType`属性设置延迟加载。将`fetchType`设置为`lazy`即可开启延迟加载。

示例:

```xml

<association property="user" column="user_id" fetchType="lazy" select="getUserById"/>

```

2. 延迟加载的触发时机:当访问关联对象时,例如调用关联对象的方法或访问关联对象的属性时,会触发实际的数据库查询,获取关联对象的数据。

3. 确保SqlSession处于打开状态:延迟加载需要保证SqlSession处于打开状态,因为在访问关联对象时,会触发实际的数据库查询,需要依赖SqlSession进行查询操作。

需要注意的是,延迟加载通常与二级缓存不兼容,因为延迟加载需要SqlSession处于打开状态才能触发数据库查询,而二级缓存的作用范围是SessionFactory级别的,无法保证SqlSession一直处于打开状态。

延迟加载的优点是能够减少数据库查询的次数,提高查询的效率。但在使用延迟加载时,需要避免出现N+1查询的问题,即在遍历关联集合或访问关联集合中的对象时,会多次触发数据库查询。可以使用MyBatis的关联预加载功能或手动调整查询策略,以避免N+1查询的性能问题。

MyBatis中的事务控制是如何实现的?

在MyBatis中,事务控制是通过基于JDBC的事务管理实现的。MyBatis本身并不提供事务管理功能,而是利用底层的JDBC连接来完成事务控制。

MyBatis使用以下对象实现事务控制:

1. SqlSessionFactory:在MyBatis的配置文件(`mybatis-config.xml`)中配置数据源和事务管理器。SqlSessionFactory负责创建和管理数据库连接。

2. SqlSession:SqlSession是与数据库交互的主要接口,它提供了执行SQL语句和管理事务的方法。

3. Transaction:Transaction接口是MyBatis用来控制事务的核心接口。MyBatis通过Transaction接口提供了开始事务、提交事务、回滚事务等方法来进行事务管理。

事务控制的基本使用方式如下:

1. 手动管理事务:通过SqlSession的`beginTransaction()`方法手动开始事务。

2. 提交事务:通过SqlSession的`commit()`方法手动提交事务。在提交事务之前,所有的数据库操作都会在一个事务中执行。

3. 回滚事务:通过SqlSession的`rollback()`方法手动回滚事务。当出现异常或需要撤销之前的操作时,可以回滚事务以保持数据的一致性。

示例代码:

```java
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    // 手动开始事务
    sqlSession.beginTransaction();

    // 执行数据库操作

    // 手动提交事务
    sqlSession.commit();

} catch (Exception e) {
    // 出现异常,回滚事务
    sqlSession.rollback();
} finally {
    // 关闭SqlSession
    sqlSession.close();
}
```

需要注意的是,MyBatis并不强制要求使用手动管理事务,可以通过配置Transaction的行为来实现自动提交或自动回滚事务。可以在MyBatis的配置文件中配置事务管理器(TransactionManager),通过配置文件设定自动提交、读写分离等事务特性。

通过上述方式,MyBatis实现了对事务的管理和控制,使得开发人员可以方便地进行事务操作,保证数据的一致性和完整性。

MyBatis的常见性能调优手段有哪些?

对于MyBatis的性能调优,以下是一些常见的手段和技巧:

1. 合理设计SQL语句:

   - 编写高效的SQL语句,避免不必要的字段查询和重复查询。

   - 使用索引来优化查询性能,确保数据库表格上存在合适的索引。

   - 避免在循环中执行SQL查询,尽量通过批量操作或者Join语句减少数据库访问。

2. 使用缓存:

   - 配置合适的缓存机制,如二级缓存,以减少对数据库的查询次数。

   - 根据业务场景设置合适的缓存过期策略和调整缓存大小。

3. 单独查询和延迟加载:

   - 使用关联查询(Join)避免N+1查询问题,减少数据库访问。

   - 合理使用延迟加载(Lazy Loading),在需要时才加载关联对象,减少不必要的查询。

4. 批量插入和更新:

   - 对于批量插入或更新的场景,使用MyBatis提供的批量操作功能,减少数据库访问次数。

5. 数据库连接池优化:

   - 配置合适的数据库连接池,如HikariCP或Druid,调整连接池大小和参数,以提高连接获取和释放的效率。

6. 预编译SQL语句:

   - 预编译SQL语句可以提高SQL的执行性能,避免每次执行都编译SQL。

7. 使用分页查询:

   - 对于大数据量的查询结果,使用分页查询,只加载需要的数据,减轻数据库负担。

8. 防止SQL注入:

   - 使用预编译SQL语句或者使用MyBatis提供的参数处理功能,以防止SQL注入攻击。

9. 监控和日志:

   - 配置合适的日志级别,记录关键操作的日志以进行排查和优化。

   - 使用监控工具如Druid监控,监控数据库连接池和SQL执行统计信息。

需要根据具体的应用场景和需求进行性能调优,综合考虑数据库结构、SQL语句设计、连接池优化等方面来提高MyBatis的性能。同时,通过分析应用的瓶颈和使用监控工具来定位潜在的性能问题。

MyBatis中如何处理批量操作?

在MyBatis中,可以使用批量操作功能来优化批量插入(batchInsert)、批量更新(batchUpdate)、批量删除(batchDelete)等操作的性能。MyBatis提供了两种方式来实现批量操作:

1. 使用 `<foreach>` 元素:

   - 创建一个 `<foreach>` 元素,设置 `collection` 属性为要循环的集合。

   - 在 `<foreach>` 元素内部编写SQL语句,并通过 `${}` 语法引用集合中的元素。

   - 使用 SQL 的 `VALUES` 关键字来批量插入或 `UPDATE` 的 `CASE WHEN` 语句来批量更新。

示例:
```xml
<!-- 批量插入 -->
<insert id="batchInsert" parameterType="java.util.List">
  INSERT INTO table_name (column1, column2)
  VALUES
  <foreach collection="list" item="item" separator=",">
    (#{item.field1}, #{item.field2})
  </foreach>
</insert>

<!-- 批量更新 -->
<update id="batchUpdate" parameterType="java.util.List">
  UPDATE table_name
  <set>
    <foreach collection="list" item="item" separator=",">
      column1 = #{item.field1},
      column2 = #{item.field2}
    </foreach>
  </set>
  WHERE id IN
  <foreach collection="list" item="item" separator="," open="(" close=")">
    #{item.id}
  </foreach>
</update>

<!-- 批量删除 -->
<delete id="batchDelete" parameterType="java.util.List">
  DELETE FROM table_name
  WHERE id IN
  <foreach collection="list" item="item" separator="," open="(" close=")">
    #{item}
  </foreach>
</delete>
```

2. 使用内置的批量操作方法:

   - 使用 `SqlSession` 的 `insert`、`update` 和 `delete` 方法,并传入带有相同ID的SQL语句和相应的参数列表。

   - 这些方法会自动将批量操作参数拆分并提交给JDBC驱动程序进行批量处理。

示例:
```java
List<YourObject> list = new ArrayList<>();
// 添加要操作的对象到 list

// 批量插入
sqlSession.insert("yourMapper.batchInsert", list);

// 批量更新
sqlSession.update("yourMapper.batchUpdate", list);

// 批量删除
sqlSession.delete("yourMapper.batchDelete", list);
```

需要注意的是,具体使用哪种方式取决于个人偏好和具体实现场景。使用 `<foreach>` 元素的方式更为灵活,适用于复杂的批量操作,而内置的批量操作方法则更为简单和快捷,适用于简单的批量操作需求。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于SSMSpring+SpringMVC+MyBatis)的管理系统是一种常见的Web应用程序,它使用Spring框架作为应用程序的核心,SpringMVC框架作为Web层的控制器,MyBatis框架作为数据访问层的ORM框架。这种管理系统可以用于各种企业级应用程序,例如人力资源管理系统、客户关系管理系统、库存管理系统等。它具有易于扩展、高效、安全等优点,是现代企业信息化建设的重要组成部分。 ### 回答2: SSM是指基于SpringSpringMVCMyBatis这三个框架技术实现的一种Web应用开发模式。在SSM框架中,Spring框架主要作为IoC容器和Bean工厂,提供依赖注入、事务管理、AOP等功能,SpringMVC框架主要负责Web层的控制器部分,处理HTTP请求和响应,而MyBatis框架则用于持久层的数据访问和管理,提供了高效且易于维护的数据库访问操作。 基于SSM框架的管理系统可以分为前台和后台两个系统。前台主要面向普通用户,提供浏览、查询、注册、登录等功能,让用户能够方便地使用系统。后台主要面向管理员或管理人员,提供对系统中各种业务数据的管理、修改、删除等功能,让管理人员能够对系统运行情况进行有效的监控和控制。 在基于SSM框架的管理系统中,需要进行技术选型、模块设计、业务实现等工作。首先,需要根据具体需求选择合适的技术方案和架构模式。其次,需要对各个模块进行梳理,按照功能划分,确定模块之间的关系和交互方式,最终实现整个系统的业务逻辑。同时,需要注意系统的可扩展性、可维护性和安全性,保证系统的数据安全,同时能够满足系统的不断发展和升级的需要。 总之,基于SSM框架的管理系统,可以通过合理运用SpringSpringMVCMyBatis等技术,实现系统中的各种业务逻辑。开发人员需要具备扎实的Java技术和Web开发经验,同时需要熟悉相关的数据库技术和网络协议,才能够顺利地完成系统的设计和开发。 ### 回答3: SSM是目前非常流行的一种技术架构,它是SpringSpringMVCMyBatis三个框架的结合,每个框架具有自己的优势和功能,通过整合,可以快速地搭建一个高效、可维护的管理系统。 在SSM框架下,可以将系统分为三层:表现层、业务层和持久层。表现层由SpringMVC处理用户请求和响应,业务层由Spring实现,而持久层则使用MyBatis实现数据库交互。 在搭建一个基于SSM的管理系统时,首先需要进行配置。Spring的配置包括Spring的核心配置文件、数据源的配置和事务的配置;SpringMVC的配置包括MVC配置文件、拦截器等;MyBatis的配置包括数据库连接池、Mapper文件和MyBatis的配置文件等。这些都需要进行详细的配置。 在系统开发中,可以通过Maven对项目进行管理,比如添加依赖、打包等。同时,也可以使用Spring Security对系统进行安全性的保护,实现权限控制等功能。 在具体的业务实现中,可以根据需要添加各种插件、拦截器和过滤器等,还可以使用Redis等缓存技术,提高系统的性能和效率。 总的来说,基于SSM的管理系统具有以下优点:首先,框架的整合可以提高开发效率,减少重复代码。其次,各个框架都具有良好的扩展性和可维护性,方便对系统进行升级和调整。最后,使用Maven进行项目管理,可以更好地管理依赖,提高项目效率。 当然,也需要注意SSM框架的缺点,比如框架整合带来的额外配置和调试成本,以及MyBatis可能存在的一些瓶颈等问题。综上所述,基于SSM的管理系统适合中小型项目,能够提高开发效率,降低开发难度,实现快速迭代和维护,是一种非常实用的技术方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值