Mybatis持久层 -- 原理总结

mybatis – 属性


起源

MyBatis 本是 Apache 的一个开源项目——iBatis,2010 年这个项目由 Apache Software Foundation 迁移到了 Google Code,并且改名为 MyBatis。

定义

MyBatis 是一个基于 Java 的持久层框架。MyBatis 提供的持久层框架包括 SQL Maps 和 Data Access Objects(DAO)

表现

MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJO映射成数据库中的记录。


常用持久层Hibernate 和 MyBatis 的区别

之前使用Hibernate重量级的框架,全自动,自动对应。简单说说几点区别

  • 第一点肯定都是sql方面的表现
    Hibernate 不需要编写大量的 SQL,就可以完全映射就可以进行操作。但会过多的消耗性能。

  • MyBatis 手动编写 SQL半自动,支持动态 SQL、处理列表、动态生成表名、支持存储过程。相对偏向自由一些,同时可以调节一些性能 缺点在于需要编写过多代码

开发方面

  • MyBatis 是一个半自动映射的框架,因此 MyBatis 需要手动匹配 POJO、SQL 和映射关系,不过可以通过逆向工程进行实现。

  • Hibernate 是一个全表映射的框架,只需提供 POJO 和映射关系即可。

Hibernate 优势

  • Hibernate 的 DAO 层开发比 MyBatis 简单
  • Hibernate 对对象的维护和缓存要比 MyBatis 好
  • Hibernate 数据库移植性很好,
  • Hibernate 有更好的二级缓存机制,可以使用第三方缓存。MyBatis 本身提供的缓存机制不佳。

Mybatis优势

  • MyBatis 可以进行更为细致的 SQL 优化,可以减少查询字段。
  • MyBatis 更容易掌握,而 Hibernate 门槛比较高。

mybatis – 工作原理简单入门

在这里插入图片描述
Spring boot 可以通过@MapperScan注解进行扫包,可以通过@Mapper 指定。Spring 需要配置Mybatis进行xml映射

Spring Resources下配置mybatis-config.xml 找到对应的mapper扫到的mapper接口

  • 1)读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。

  • 2)加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。

  • 3)构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。

  • 4)创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。

  • 5)Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。

  • 6)MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。

  • 7)输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。

  • 8)输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。

可以参照一下手动写的sql去对比

static {
		// 注册驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
 
	// 通过构造方法初始化连接
	public MyDataSourcePool() {
		for (int i = 0; i < INIT_CONNECTIONS; i++) {
			try {
				Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
				pool.addLast(conn);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
 
	// 获取数据库连接
	public Connection getConnection() {
		Connection conn = null;
		lock.lock();
		try {
			while (pool.size() < 0) {
				try {
					condition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			if (!pool.isEmpty()) {
				conn = pool.removeFirst();
			}
			return conn;
		} finally {
			lock.unlock();
		}
	}
 
	// 释放数据库连接
	public void releaseConnection(Connection conn) {
		if (conn != null) {
			lock.lock();
			try {
				// 释放连接过程就是把连接放回连接池过程
				pool.addLast(conn);
				condition.signal();
			} finally {
				lock.unlock();
			}
		}
	}


区别手动写法,进行工厂sqlSession进行管理方便连接的性能。

Mybatis – 核心组件罗列

在这里插入图片描述

  • 1)SqlSessionFactoryBuilder(构造器):它会根据配置或者代码来生成 SqlSessionFactory,采用的是分步构建的 Builder 模式。

  • 2)SqlSessionFactory(工厂接口):依靠它来生成 SqlSession,使用的是工厂模式。

  • 3)SqlSession(会话):一个既可以发送 SQL 执行返回结果,也可以获取 Mapper 的接口。在现有的技术中,一般我们会让其在业务逻辑代码中“消失”,而使用的是 MyBatis 提供的 SQL Mapper 接口编程技术,它能提高代码的可读性和可维护性。

  • 4)SQL Mapper(映射器):MyBatis 新设计存在的组件,它由一个 Java 接口和 XML 文件(或注解)构成,需要给出对应的 SQL 和映射规则。它负责发送 SQL 去执行,并返回结果。

实现

MyBatis 首先是使用配置或者代码去生产 SqlSessionFactory,而 MyBatis 提供了构造器 SqlSessionFactoryBuilder。

它提供了一个类 org.apache.ibatis.session.Configuration 作为引导,采用的是 Builder 模式。

在 MyBatis 中,既可以通过读取配置的 XML 文件的形式生成 SqlSessionFactory,也可以通过 Java 代码的形式去生成 SqlSessionFactory。

SqlSessionFactory 是一个接口,在 MyBatis 中它存在两个实现类:SqlSessionManager 和 DefaultSqlSessionFactory

一般而言,具体是由 DefaultSqlSessionFactory 去实现的,而 SqlSessionManager 使用在多线程的环境中,它的具体实现依靠 DefaultSqlSessionFactory,它们之间的关系如图
在这里插入图片描述
使用 XML 构建 SqlSessionFactory

创建mybatis-config.xml

<?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>
    <typeAliases><!--别名-->
        <typeAliases alias="user" type="com.mybatis.po.User"/>
    </typeAliases>
    <!-- 数据库环境 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用JDBC的事务管理 -->
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <!-- MySQL数据库驱动 -->
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <!-- 连接数据库的URL -->
                <property name="url"
                    value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8" />
                <property name="username" value="root" />
                <property name="password" value="1234" />
            </dataSource>
        </environment>
    </environments>
    <!-- 将mapper文件加入到配置文件中 -->
    <mappers>
        <mapper resource="com/mybatis/mapper/UserMapper.xml" />
    </mappers>
</configuration>

SpringBoot 可以通过@Bean 配置对应的实体组件bean

有了基础配置文件,就可以用一段很简短的代码来生成 SqlSessionFactory

SqlSessionFactory factory = null;
String resource = "mybatis-config.xml";
InputStream is;
try {
    InputStream is = Resources.getResourceAsStream(resource);
    factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
    e.printStackTrace();
}

使用代码创建 SqlSessionFactory

/ 数据库连接池信息
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword ("1128");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
dataSource.setDefeultAutoCommit(false);
// 采用 MyBatis 的 JDBC 事务方式
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment ("development", transactionFactory, dataSource);
// 创建 Configuration 对象
Configuration configuration = new Configuration(environment);
// 注册一个 MyBatis 上下文别名
configuration.getTypeAliasRegistry().registerAlias("role", Role.class);
// 加入一个映射器
configuration.addMapper(RoleMapper.class);
//使用 SqlSessionFactoryBuilder 构建 SqlSessionFactory
SqlSessionFactory SqlSessionFactory =
new SqlSessionFactoryBuilder().build(configuration);
return SqlSessionFactory;

SqlSession 控制数据库事务的方法

//定义 SqlSession
SqlSession sqlSession = null;
try {
    // 打开 SqlSession 会话
    sqlSession = SqlSessionFactory.openSession();
    // some code...
    sqlSession.commit();    // 提交事务
} catch (IOException e) {
    sqlSession.rollback();  // 回滚事务
}finally{
    // 在 finally 语句中确保资源被顺利关闭
    if(sqlSession != null){
        sqlSession.close();
    }
}

MyBatis – 核心组件的作用域以及生命周期

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 的作用在于创建 SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 SqlSessionFactory 的方法中,而不要让其长期存在。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)

SqlSessionFactory

SqlSessionFactory 可以被认为是一个数据库连接池,它的作用是创建 SqlSession 接口对象。因为 MyBatis 的本质就是 Java 对数据库的操作,所以 SqlSessionFactory 的生命周期存在于整个 MyBatis 的应用之中,所以一旦创建了 SqlSessionFactory,就要长期保存它,直至不再使用 MyBatis 应用,所以可以认为 SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。

由于 SqlSessionFactory 是一个对数据库的连接池,所以它占据着数据库的连接资源。如果创建多个 SqlSessionFactory,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。

因此在一般的应用中我们往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以说 SqlSessionFactory 的最佳作用域是应用作用域。

SqlSession

如果说 SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback 等方法,提交或者回滚事务。

所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try…catch…finally… 语句来保证其正确关闭。

所以 SqlSession 的最佳的作用域是请求或方法作用域。

Mapper

Mapper 是一个接口,它由 SqlSession 所创建,所以它的最大生命周期至多和 SqlSession 保持一致,尽管它很好用,但是由于 SqlSession 的关闭,它的数据库连接资源也会消失,所以它的生命周期应该小于等于 SqlSession 的生命周期。Mapper 代表的是一个请求中的业务处理,所以它应该在一个请求中,一旦处理完了相关的业务,就应该废弃它。


MyBatis – settings属性配置详解

配置项作用配置选项默认值
cacheEnabled该配置影响所有映射器中配置缓存的全局开关true/falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。在特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态true/falsefalse
aggressiveLazyLoading当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载true/falsetrue
multipleResultSetsEnabled是否允许单一语句返回多结果集(需要兼容驱动)true/falsetrue
useColumnLabel使用列标签代替列名。不同的驱动会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果true/falsetrue
useGeneratedKeys允许JDBC 支持自动生成主键,需要驱动兼容。如果设置为 true,则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)true/falsefalse
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。NONE 表示取消自动映射。
PARTIAL 表示只会自动映射,没有定义嵌套结果集和映射结果集。
FULL 会自动映射任意复杂的结果集(无论是否嵌套) NONE、PARTIAL、FULLPARTIALautoMappingUnkno wnColumnBehavior指定自动映射当中未知列(或未知属性类型)时的行为。 默认是不处理,只有当日志级别达到 WARN 级别或者以下,才会显示相关日志,如果处理失败会抛出 SqlSessionException 异常
defaultExecutorType配置默认的执行器。SIMPLE 是普通的执行器;REUSE 会重用预处理语句(prepared statements);BATCH 执行器将重用语句并执行批量更新SIMPLE、REUSE、BATCHSIMPLE
defaultStatementTimeout设置超时时间,它决定驱动等待数据库响应的秒数任何正整数Not Set (null)
defaultFetchSize设置数据库驱动程序默认返回的条数限制,此参数可以重新设置任何正整数Not Set (null)
safeRowBoundsEnabled允许在嵌套语句中使用分页(RowBounds)。如果允许,设置 falsetrue/falsefalse
safeResultHandlerEnabled允许在嵌套语句中使用分页(ResultHandler)。如果允许,设置falsetrue/falsetrue
mapUnderscoreToCamelCase是否开启自动驼峰命名规则映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射true/falsefalse
localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速联复嵌套査询。默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlScssion 的不同调用将不会共享数据SESSIONSTATEMENT
jdbcTypeForNull当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHERNULL、VARCHAR、OTHEROTHER
lazyLoadTriggerMethods指定哪个对象的方法触发一次延迟加载equals、clone、hashCode、toString
callSettersOnNulls指定当结果集中值为 null 时,是否调用映射对象的 setter(map 对象时为 put)方法,这对于 Map.kcySet() 依赖或 null 值初始化时是有用的。注意,基本类型(int、boolean 等)不能设置成 nulltrue/falsefalse
logPrefix指定 MyBatis 增加到日志名称的前缀任何字符串Not set
loglmpl指定 MyBatis 所用日志的具体实现,未指定时将自动査找SLF4JLOG4J/LOG4J2/JDK_LOGGING/COMMONS_LOGGING/STDOUT_LOGGING/NO_LOGGING

这里给出一个全量的配置样例,如下所示。

<settings>
    <setting name="cacheEnabled" value="true"/>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="multipleResultSetsEnabled" value="true"/>
    <setting name="useColumnLabel" value="true"/>
    <setting name="useGeneratedKeys" value="false"/>
    <setting name="autoMappingBehavior" value="PARTIAL"/>
    <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
    <setting name="defaultExecutorType" value="SIMPLE"/>
    <setting name="defaultStatementTimeout" value="25"/>
    <setting name="defaultFetchSize" value="100"/>
    <setting name="safeRowBoundsEnabled" value="false"/>
    <setting name="mapUnderscoreToCamelCase" value="false"/>
    <setting name="localCacheScope" value="SESSION"/>
    <setting name="jdbcTypeForNull" value="OTHER"/>
    <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

MyBatis – 整合至Spring框架融合

导入架包

支持包

  • aopalliance-1.0.jar
  • aspectjweaver-1.6.9.jar

连接池支持包

  • commons-c3p0-2.2.0.jar(连接池按自己选择,配置基本没什么较大区别)

数据库包

  • mysql-connector-java-5.1.25-bin.jar

Spring融合包

  • mybatis-spring-1.3.1.jar

Spring核心包

  • spring-aop-3.2.13.RELEASE.jar
  • spring-aspects-3.2.13.RELEASE.jar
  • spring-beans-3.2.13.RELEASE.jar
  • spring-context-3.2.13.RELEASE.jar
  • spring-core-3.2.13.RELEASE.jar
  • spring-expression-3.2.13.RELEASE.jar
  • spring-jdbc-3.2.13.RELEASE.jar
  • spring-tx-3.2.13.RELEASE.jar

在mybatis-config.xml配置自己需要的Settings

创建 mybatis-config.xm

一般项目常规配置

<?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>
	<settings>
		//该配置影响所有映射器中配置缓存的全局开关
		<setting name="cacheEnabled" value="true"/>
		//延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。在特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态
		<setting name="lazyLoadingEnabled" value="true"/>
		//是否允许单一语句返回多结果集(需要兼容驱动)
		<setting name="multipleResultSetsEnabled" value="true"/>
		//使用列标签代替列名。不同的驱动会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果
		<setting name="useColumnLabel" value="true"/>
		//允许JDBC 支持自动生成主键,需要驱动兼容。如果设置为 true,则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)
		<setting name="useGeneratedKeys" value="true"/>
		//配置默认的执行器。SIMPLE 是普通的执行器;REUSE 会重用预处理语句(prepared statements);BATCH 执行器将重用语句并执行批量更新
		<setting name="defaultExecutorType" value="SIMPLE"/>
		//	设置超时时间,它决定驱动等待数据库响应的秒数
		<setting name="defaultStatementTimeout" value="25000"/>
		//指定当结果集中值为 null 时,是否调用映射对象的 setter(map 对象时为 put)方法,这对于 Map.kcySet() 依赖或 null 值初始化时是有用的。注意,基本类型(int、boolean 等)不能设置成 null
		<setting name="callSettersOnNulls" value="true"/>
		//	指定 MyBatis 所用日志的具体实现,未指定时将自动査找
		<!--<setting name="logImpl" value="STDOUT_LOGGING" />-->
	</settings>
</configuration>

Spring-ApplicationContext.xml配置数据

创建Spring-ApplicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- 扫描service包下所有使用注解的类型 -->
	<context:component-scan base-package="com.SpringTest" />

	<!-- 配置整合mybatis过程 -->
	  <!--集中管理db.properties-->
    <bean id="initDBPropertyConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:db.properties</value>
            </list>
        </property>
        <property name="placeholderPrefix" value="${"/>
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
    </bean>
 />
<!--

    <!--配置文件-->
    <bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath:xx.properties</value>
                <value>classpath:xx.properties</value>
                <value>classpath:xx.properties</value>
            </list>
        </property>
    </bean>
    
     <!--jndi 配置场外配置文件-->
    <jee:jndi-lookup id="dataSource" jndi-name="${jndi.name}" proxy-interface="javax.sql.DataSource"/>
-->

	<!-- 2.数据库连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<!-- 配置连接池属性 -->
		<property name="driverClass" value="${jdbc.driver}" />
		<property name="jdbcUrl" value="${jdbc.url}" />
		<property name="user" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />

		<!-- c3p0连接池的私有属性 -->
		<property name="maxPoolSize" value="30" />
		<property name="minPoolSize" value="10" />
		<!-- 关闭连接后不自动commit -->
		<property name="autoCommitOnClose" value="false" />
		<!-- 获取连接超时时间 -->
		<property name="checkoutTimeout" value="10000" />
		<!-- 当获取连接失败重试次数 -->
		<property name="acquireRetryAttempts" value="2" />
	</bean>

	<!-- 3.配置SqlSessionFactory对象 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 注入数据库连接池 -->
		<property name="dataSource" ref="dataSource" />
		<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
		<property name="configLocation" value="classpath:mybatis-config.xml" />
		<!-- 映射Resources下面mapper下面所有包xml文件 -->
		<!-- xml 用mapper namespace="com.springTest.dao.xxxx" 指定为dao指定的映射文件 -->
		<property name="mapperLocations" value="classpath:mapper/**/*.xml" />
	</bean>

	<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 注入sqlSessionFactory -->
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
		<!-- 给出需要扫描Dao接口包,会自动映射到 classpath:mapper/**/*.xml寻找-->
		<property name="basePackage" value="com.springTest.dao" />
	</bean>
</beans>

	<!-- 配置事务管理器 -->
 <tx:annotation-driven/>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

db.properties

创建 db.properties

根据自己需求添加参数

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=1234
jdbc.url=jdbc:mysql://127.0.0.1:3306/springtest?seUnicode=true&amp;characterEncoding=utf-8

spring-MVC.xml

创建spring -MVC

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
	<!-- 配置SpringMVC -->
	<!-- 1.开启SpringMVC注解模式 -->

	<mvc:annotation-driven />
	
	 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	 	<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
	 	<property name="prefix" value="/WEB-INF/jsp/" />
	 	<property name="suffix" value=".jsp" />
	 </bean>
	 
	 <!-- 4.扫描web相关的bean -->
	 <context:component-scan base-package="com.SpringTest.Controller" />
</beans>



更改XML

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


    <!--加载配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/Spring-ApplicationContext.xml</param-value>
    </context-param>
<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>
		org.springframework.web.servlet.DispatcherServlet</servlet-class>
	
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring/spring-mvc.xml</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<!-- 默认匹配所有的请求 -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>
 

Spring boot 配置

引入启动包

<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>1.1.1</version>
</dependency>

application.properties 添加数据库和mybatis配置

mybatis.type-aliases-package=com.neo.entity //对应实体类的包名
mybatis.mapper-locations= classpath:mybatis/*.xml 指定地址

或者

@MapperScan("com.XXX.mapper")

引入启动包配置mybatis 映射,前提是mysql 会自动被mybatis 管理,注入连接,交给持久化管理
扫描@Mapper的包注入mybatis 进行映射返回实体


MyBatis – 高级注解使用

进行和项目之间类型指定。 mapper 通过id进行映射

 <resultMap id="BaseResultMap" type="com.neo.entity.UserEntity" >
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="userName" property="userName" jdbcType="VARCHAR" />
        <result column="passWord" property="passWord" jdbcType="VARCHAR" />
        <result column="user_sex" property="userSex" javaType="com.neo.enums.UserSexEnum"/>
        <result column="nick_name" property="nickName" jdbcType="VARCHAR" />
    </resultMap>
    
    <sql id="Base_Column_List" >
        id, userName, passWord, user_sex, nick_name
    </sql>

where

<select id="queryUserByWhere" parameterType="user" resultType="user">
	<!-- SELECT id, username, birthday, sex, address FROM `user` -->
	<!-- 使用include标签加载sql片段;refid是sql片段id -->
	SELECT <include refid="userFields" /> FROM `user`
	<!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 -->
	<where>
		<if test="sex != null">
			AND sex = #{sex}
		</if>
		<if test="username != null and username != ''">
			AND username LIKE
			'%${username}%'
		</if>
	</where>
</select>

循环遍历 list

<!-- 根据ids查询用户 -->
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
	SELECT * FROM `user`
	<where>
		<!-- foreach标签,进行遍历 -->
		<!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
		<!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
		<!-- open:在前面添加的sql片段 -->
		<!-- close:在结尾处添加的sql片段 -->
		<!-- separator:指定遍历的元素之间使用的分隔符 -->
		<foreach collection="ids" item="item" open="id IN (" close=")"
			separator=",">
			#{item}
		</foreach>
	</where>
</select>

association
对于映射类里面有实体类 使用association 进行指定

<resultMap type="order" id="orderUserResultMap">
	<id property="id" column="id" />
	<result property="userId" column="user_id" />
	<result property="number" column="number" />
	<result property="createtime" column="createtime" />
	<result property="note" column="note" />

	<!-- association :配置一对一属性 -->
	<!-- property:order里面的User属性名 -->
	<!-- javaType:属性类型 -->
	<association property="user" javaType="user">
		<!-- id:声明主键,表示user_id是关联查询对象的唯一标识-->
		<id property="id" column="user_id" />
		<result property="username" column="username" />
		<result property="address" column="address" />
	</association>

</resultMap>

<!-- 一对一关联,查询订单,订单内部包含用户属性 -->
<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
	SELECT
	o.id,
	o.user_id,
	o.number,
	o.createtime,
	o.note,
	u.username,
	u.address
	FROM
	`order` o
	LEFT JOIN `user` u ON o.user_id = u.id
</select>

一对多

<resultMap type="user" id="userOrderResultMap">
	<id property="id" column="id" />
	<result property="username" column="username" />
	<result property="birthday" column="birthday" />
	<result property="sex" column="sex" />
	<result property="address" column="address" />

	<!-- 配置一对多的关系 -->
	<collection property="orders" javaType="list" ofType="order">
		<!-- 配置主键,是关联Order的唯一标识 -->
		<id property="id" column="oid" />
		<result property="number" column="number" />
		<result property="createtime" column="createtime" />
		<result property="note" column="note" />
	</collection>
</resultMap>

<!-- 一对多关联,查询订单同时查询该用户下的订单 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
	SELECT
	u.id,
	u.username,
	u.birthday,
	u.sex,
	u.address,
	o.id oid,
	o.number,
	o.createtime,
	o.note
	FROM
	`user` u
	LEFT JOIN `order` o ON u.id = o.user_id
</select>

返回id useGeneratedKeys

<insert id="insertXXX" useGeneratedKeys="true" keyProperty="id" parameterType="com.lan.vote.model.User">
        //SQL语句
</insert>
  • 插入返回主键id useGeneratedKeys 默认值是:false。

  • keyProperty: 标记一个属性, MyBatis 会通过 getGeneratedKeys 或者通过 insert 语句的 selectKey 子元素设置它的值。默认: 不设置。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值