mybatis学习

mybatis 学习

一:使用原始 JDBC连接数据库

1:获取数据库连接DBUtils

package com.lock.redislock.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBUtils {
     

    private static final String URL="jdbc:mysql://127.0.0.1:3306/qb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false";
    private static final String USER="root";
    private static final String PASSWORD="1234";

    private static final String driverClassName="com.mysql.cj.jdbc.Driver";

    private static Connection conn=null;

    static {
     
        try {
     
            //1.加载驱动程序
            Class.forName(driverClassName);
            //2.获得数据库的连接
            conn=DriverManager.getConnection(URL, USER, PASSWORD);
        } catch (ClassNotFoundException e) {
     
            e.printStackTrace();
        } catch (SQLException e) {
     
            e.printStackTrace();
        }
    }
    //将获得的数据库与java的链接返回(返回的类型为Connection)
    public static Connection getConnection(){
     
        return conn;
    }

}

2:进行 sql 语句查询 修改操作

				//获取连接				
				Connection connection = DBUtils.getConnection();
        //通过数据库的连接操作数据库,实现增删改查(使用Statement类)
        Statement statement = connection.createStatement();
        //调用查询操作
        ResultSet resultSet = statement.executeQuery("select phone,name FROM t_user WHERE id in (1,23)");
        //处理数据库的返回结果(使用ResultSet类)
        while (resultSet.next()){
     
            String phone = resultSet.getString("phone");
            String name = resultSet.getString("name");
            System.out.println(phone + "===" + name);
        }
        //调用修改操作
        statement.executeUpdate("update t_user set name = 'lyl',phone='12312371237' where id = 23");
				//关闭资源
        statement.close();
        connection.close();

3:使用占位符

				Connection connection = DBUtils.getConnection();
				try {
     
          	//
            PreparedStatement pre = connection.prepareStatement("SELECT phone,name FROM t_user WHERE id in (?,?) order by id desc");
            pre.setString(1,"13");
            pre.setString(2,"1");
            ResultSet resultSet = pre.executeQuery();
            while (resultSet.next()){
     
                String phone = resultSet.getString("phone");
                String name = resultSet.getString("name");
                System.err.println(phone + "===" + name);
            }
        } catch (SQLException e) {
     
            e.printStackTrace();
        }

4:设置批量处理

				//设置事务不自动提交
         conn.setAutoCommit(false);
         //3.通过数据库的连接操作数据库,实现增删改查(使用Statement类)
         Statement st=conn.createStatement();
         st.addBatch("insert into user(user_name,user_password) values('小时2','456')");
         st.addBatch("insert into user(user_name,user_password) values('小时3','4561')");
         
         st.executeBatch();
         conn.commit();
         
         //关闭资源    
         st.close();    
         conn.close();

二:使用mybatis 连接数据库

1.配置mybatis-config.xml



<configuration>

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC" />
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.cj.jdbc.Driver">property>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/qb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false">property>
            <property name="username" value="root">property>
            <property name="password" value="1234">property>
        dataSource>
    environment>
environments>


<mappers>
    <mapper resource="UserMapper.xml"/>
mappers>
configuration>

2:pow.xml 配置


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0modelVersion>
	
	<groupId>com.lockgroupId>
	<artifactId>redis-lockartifactId>
	<version>0.0.1-SNAPSHOTversion>
	<name>redis-lockname>
	<description>Demo project for Spring Bootdescription>
	<packaging>warpackaging>

	<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.3.RELEASEversion>
		<relativePath/>
	parent>

	<properties>
		<java.version>1.8java.version>
	properties>

	<dependencies>

		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-data-redisartifactId>
			
		dependency>

		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		<dependency>
			<groupId>org.redissongroupId>
			<artifactId>redissonartifactId>
			<version>2.2.13version>
		dependency>
		<dependency>
			<groupId>mysqlgroupId>
			<artifactId>mysql-connector-javaartifactId>
			<version>8.0.11version>
		dependency>

		<dependency>
			<groupId>com.alibabagroupId>
			<artifactId>druidartifactId>
			<version>1.1.9version>
		dependency>

		<dependency>
			<groupId>org.projectlombokgroupId>
			<artifactId>lombokartifactId>
			<optional>trueoptional>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-testartifactId>
			<scope>testscope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintagegroupId>
					<artifactId>junit-vintage-engineartifactId>
				exclusion>
			exclusions>
		dependency>
		<dependency>
			<groupId>io.projectreactorgroupId>
			<artifactId>reactor-testartifactId>
			<scope>testscope>
		dependency>
		
		<dependency>
			<groupId>redis.clientsgroupId>
			<artifactId>jedisartifactId>
			<version>2.7.3version>
		dependency>
		
		<dependency>
			<groupId>com.alibabagroupId>
			<artifactId>fastjsonartifactId>
			<version>1.2.68version>
		dependency>
		<dependency>
			<groupId>org.mybatisgroupId>
			<artifactId>mybatisartifactId>
			<version>3.5.2version>
		dependency>
	dependencies>

	<repositories>
		<repository>
			<id>nexus-aliyunid>
			<name>Nexus aliyunname>
			<layout>defaultlayout>
			<url>http://maven.aliyun.com/nexus/content/groups/publicurl>
			<snapshots>
				<enabled>falseenabled>
			snapshots>
			<releases>
				<enabled>trueenabled>
			releases>
		repository>
	repositories>
	<profiles>
		
		<profile>
			<id>localid>
			<properties>
				<profileActive>localprofileActive>
			properties>
			<activation>
				<activeByDefault>trueactiveByDefault>
			activation>
		profile>
		
		<profile>
			<id>devid>
			<properties>
				<profileActive>devprofileActive>
			properties>
		profile>
		
		<profile>
			<id>prodid>
			<properties>
				<profileActive>prodprofileActive>
			properties>
		profile>
	profiles>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.bootgroupId>
				<artifactId>spring-boot-maven-pluginartifactId>
				<version>2.0.6.RELEASEversion>
				<configuration>
					<mainClass>com.lock.redislock.RedisLockApplicationmainClass>
					<layout>ZIPlayout>
				configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackagegoal>
						goals>
					execution>
				executions>
			plugin>
		plugins>
		<resources>
			
			<resource>
				<directory>src/main/resourcesdirectory>
				<filtering>truefiltering>
				<includes>
					<include>application-*.ymlinclude>
					<include>redisson-*.ymlinclude>
					<include>application.ymlinclude>
					<include>*.xmlinclude>
				includes>
			resource>
			<resource>
				<directory>src/main/javadirectory>
				<includes>
					<include>**/*.xmlinclude>
				includes>
			resource>
		resources>
	build>
project>

3:测试连接数据库

package com.lock.redislock.lyl;

import com.lock.redislock.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.util.List;
import java.util.Map;

public class MybatisTest {
     

    public static void main(String[] args) throws Exception {
     
        // 定义配置文件,相对路径,文件直接放在resources目录下
        String resource = "mybatis-config.xml";
        // 读取文件字节流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // mybatis 读取字节流,利用XMLConfigBuilder类解析文件
        // 将xml文件解析成一个 org.apache.ibatis.session.Configuration 对象
        // 然后将 Configuration 对象交给 SqlSessionFactory 接口实现类 DefaultSqlSessionFactory 管理
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // openSession 有多个重载方法, 比较重要几个是
        // 1 是否默认提交 SqlSession openSession(boolean autoCommit)
        // 2 设置事务级别 SqlSession openSession(TransactionIsolationLevel level)
        // 3 执行器类型   SqlSession openSession(ExecutorType execType)
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // mybatis 内部其实已经解析好了 mapper 和 mapping 对应关系,放在一个map中,这里可以直接获取
        // 如果看源码可以发现userMapper 其实是一个代理类MapperProxy,
        // 通过 sqlSession、mapperInterface、mechodCache三个参数构造的
        // MapperProxyFactory 类中 newInstance(MapperProxy mapperProxy)方法
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        /* insert */
        /* User user = new User();
        user.setUsername("LiuYork");
        user.setPassword("123456");
        userMapper.insertUser(user);*/
        // 由于默认 openSession() 事务是交由开发者手动控制,所以需要显示提交
        sqlSession.commit();
        /* select */
        List<Map<String,Object>> users = userMapper.selectUser(1);
        users.forEach(map->{
     
            map.forEach((k,v)->{
     
                System.out.println(k + "====" + v);
            });
        });
        sqlSession.close();
    }

}

4:jdbc 和 mybatis 进行数据插入性能比较

1:jdbc 插入 100000 条耗时 2 秒
				Connection connection = DBUtils.getConnection();
        connection.setAutoCommit(false);
        long startDate = System.currentTimeMillis();
        StringBuffer sql = new StringBuffer("INSERT INTO t_user(age,name) VALUES");
        for (int i = 0 ; i < 100000; i++){
     
            sql.append("(?,?),");
        }
        PreparedStatement pre = connection.prepareStatement(sql.toString().substring(0,sql.length() - 1));
        for (int i = 1 ; i <= 100000; i++){
     
            int a = (i-1)*2 + 1;
            pre.setString(a,a+"");
            pre.setString(a+1,"名字" + (a+ 1));
        }
        boolean resultSet = pre.execute();
        connection.commit();
        //关闭资源
        connection.close();
        pre.close();
        long endDate = System.currentTimeMillis();
        System.out.println("调用 sql 耗时 == "+(endDate-startDate)/1000+"秒");
2:mybatis插入100000条耗时7秒
 // 定义配置文件,相对路径,文件直接放在resources目录下
        String resource = "mybatis-config.xml";
        // 读取文件字节流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // mybatis 读取字节流,利用XMLConfigBuilder类解析文件
        // 将xml文件解析成一个 org.apache.ibatis.session.Configuration 对象
        // 然后将 Configuration 对象交给 SqlSessionFactory 接口实现类 DefaultSqlSessionFactory 管理
        SqlSessionFactory sqlSessionFactory = new 					SqlSessionFactoryBuilder().build(inputStream);
        inputStream.close();
        // openSession 有多个重载方法, 比较重要几个是
        // 1 是否默认提交 SqlSession openSession(boolean autoCommit)
        // 2 设置事务级别 SqlSession openSession(TransactionIsolationLevel level)
        // 3 执行器类型   SqlSession openSession(ExecutorType execType)
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // mybatis 内部其实已经解析好了 mapper 和 mapping 对应关系,放在一个map中,这里可以直接获取
        // 如果看源码可以发现userMapper 其实是一个代理类MapperProxy,
        // 通过 sqlSession、mapperInterface、mechodCache三个参数构造的
        // MapperProxyFactory 类中 newInstance(MapperProxy mapperProxy)方法
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        long startDate = System.currentTimeMillis();
        List<User> list = new ArrayList<>();
        for (int i = 0 ; i< 100000;i++){
     
            User user = new User();
            user.setAge(i+ 10);
            user.setName("sljyfl" + i);
            list.add(user);
        }
        long endDate = System.currentTimeMillis();
        System.err.println("创建插入对象耗时 == "+(endDate-startDate)/1000+"秒");
        Integer integer = userMapper.batchInsertUser(list);
        sqlSession.commit();
        System.err.println(integer);
        endDate = System.currentTimeMillis();
        System.out.println("调用 sql 耗时 == "+(endDate-startDate)/1000+"秒");
        sqlSession.close();
3:jdbc 批处理进行插入 71秒 需要每条 sql 依次插入速度很慢
				connection.setAutoCommit(false);
        String sql1="insert into t_user(age,name) " +
                "   values(?,?) ";

        PreparedStatement statement=connection.prepareStatement(sql1);
        for (int i = 0; i < 100000 ; i++) {
     
            statement.setInt(1, i);
            statement.setString(2, "bbb"+i);
            statement.addBatch();
        }
        long start=System.currentTimeMillis();
        statement.executeBatch();
        connection.commit();
        connection.close();
        statement.close();
        System.out.print("耗时:");
        System.out.println(System.currentTimeMillis()-start);
4:批量插入数据出现的异常max_allowed_packet解决方案
mysql的设置参数中max_allowed_packet过小导致操作异常
永久性解决方案:
修改方法1(配置文件持久化修改):
vim /etc/my.cnf
[mysqld]
max_allowed_packet = 100M
注意:修改配置文件以后,需要重启mysql服务才能生效。
临时解决方案,修改该值
show variables like ‘max_allowed_packet’;
set global max_allowed_packet = 10 * 1024 * 1024;
但是重启Mysql还是会恢复到默认值,所以需要写在配置文件当中
注意:
1.命令行修改时,不能用M、G,只能这算成字节数设置。配置文件修改才允许设置M、G单位。
2.命令行修改之后,需要退出当前回话(关闭当前mysql server链接),然后重新登录才能查看修改后的值。通过命令行修改只能临时生效,下次数据库重启后又复原了。
3.max_allowed_packet 最大值是1G(1073741824),如果设置超过1G,查看最终生效结果也只有1G。
5:jdbc和 mybatis性能差距原因
jdbc 和mybatis 效率差距主要因为什么?
jdbc毫无疑问比mybatis快,其中一个原因是mybatis需要去映射。映射是在内存完成,应该还好。
这个问题相当于为什么java比c c++慢。
mybatis底层终究是调用jdbc的。而映射这东西不管是对象转一些值,还是一些值转对象,都需要调用反射api的,
尽管你可以把成员变量getxx()方法对应的Method对象缓存起来,但是终究还是要调invoke的。
反射相对而言是比较影响性能的了。
看了看mybatis的底层实现,确实是调用到反射。应该就是反射这个东西比较影响性能

三:详细使用 mybatis

1:使用 mybatis 的 嵌套结果 1 对 1查询

(一次性查询出结果)

		private static void selectBlogAndAuthor(SqlSession sqlSession) {
     
        BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
        long startDate = System.currentTimeMillis();
        long endDate;
        List<BlogAndAuthor> blogAndAuthors = blogMapper.selectBlogAndAuthor(2);
        blogAndAuthors.forEach(blogAndAuthor -> {
     
            System.err.println(blogAndAuthor);
            System.err.println(blogAndAuthor.getAuthor());
        });
        endDate = System.currentTimeMillis();
        System.out.println("调用 sql 耗时 == "+(endDate-startDate)/1000+"秒");
        sqlSession.close();
    }
 <resultMap id="BlogWithAuthorResultMap" type="BlogAndAuthor">
        <id column="bid" property="bid" jdbcType="INTEGER">id>
        <result column="name" property="name" jdbcType="VARCHAR">result>
   			
        <association property="author" javaType="Author">
            <id column="author_id" property="authorId">id>
            <result column="author_name" property="authorName">result>
        association>
    resultMap>

    <select id="selectBlogAndAuthor" parameterType="int" resultMap="BlogWithAuthorResultMap">
        select * from blog b LEFT JOIN author a on b.author_id = a.author_id where b.bid = #{bid}
    select>
2:使用 mybatis 的嵌套查询 1 对 1查询

<setting name="lazyLoadingEnabled" value="true"/>


<setting name="aggressiveLazyLoading" value="false"/>
private static void selectBlogAndAuthorQuery(SqlSession sqlSession) {
     
        BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
        List<BlogAndAuthor> blogAndAuthors = blogMapper.selectBlogAndAuthorQuery(1);
        for (BlogAndAuthor blogAndAuthor : blogAndAuthors) {
     
            System.err.println(blogAndAuthor.getBid() + blogAndAuthor.getName());
            //
            //开启延迟加载时:只有调用 getAuthor() 方法的时候才会去调用 sql去查询数据库 
            //System.err.println(blogAndAuthor.getAuthor());
        }
        sqlSession.close();
    }
<resultMap id="BlogWithAuthorQueryMap" type="BlogAndAuthor">
        <id column="bid" property="bid" jdbcType="INTEGER">id>
        <result column="name" property="name" jdbcType="VARCHAR">result>
  			
        <association property="author" javaType="Author" column="author_id" select="selectAuthor" fetchType="lazy"/>
    resultMap>

    <select id="selectBlogAndAuthorQuery" parameterType="int" resultMap="BlogWithAuthorQueryMap">
        select * from blog b where b.bid = #{bid}
    select>

    <select id="selectAuthor" parameterType="int" resultType="Author">
        select author_id authorId,author_name authorName from author where author_id = #{authorId}
    select>

四:mybatis 缓存

https://www.jianshu.com/p/c553169c5921

1:测试一级缓存

Mybatis一级缓存的生命周期和SqlSession一致。

Mybatis的缓存是一个粗粒度的缓存,没有更新缓存和缓存过期的概念,同时只是使用了默认的hashmap,也没有做容量上的限定。

Mybatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,有操作数据库写的话,会引起脏数据,建议是把一级缓存的默认级别设定为Statement,即不使用一级缓存。

1:当属于同一个会话时发现两次查询只发送了一条 sql 语句,说明第二次查询命中了一级缓存

2:当切换为另外的一个会话时发现有进行了一个 sql 查询.说明一级缓存只在同一个会话中生效

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FBzgAcjX-1590648177492)(/Users/apple/Library/Application Support/typora-user-images/image-20200525144712251.png)]

同一个会话中如果进行了修改操作会去清空当前会话的一级缓存(一级缓存存在于 sqlSession 会话中)

当另外一个会话去查询数据时拿到的还是旧的数据(出现了脏数据问题)

flushCache=“true” 每次操作都去刷新一级缓存

flushCache=“false” 不去刷新一级缓存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qnUGAm7r-1590648177493)(/Users/apple/Library/Application Support/typora-user-images/image-20200525154618635.png)]

2:测试二级缓存
<mapper namespace="com.lock.redislock.mapper.BlogMapper">
  	
    <cache/>

五:mybatis 问题

1、什么是MyBatis?

答:MyBatis是一个可以自定义SQL、存储过程和高级映射的持久层框架。

2、讲下MyBatis的缓存

答:MyBatis的缓存分为一级缓存和二级缓存,一级缓存放在session里面,默认就有,二级缓存放在它的命名空间里,默认是不打开的,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置

3、Mybatis是如何进行分页的?分页插件的原理是什么?

1)Mybatis使用RowBounds对象进行分页,也可以直接编写sql实现分页,也可以使用Mybatis的分页插件。

2)分页插件的原理:实现Mybatis提供的接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql。

举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10

4、简述Mybatis的插件运行原理,以及如何编写一个插件?

1)Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis通过动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

2)实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。

5、Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?

1)Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。

2)Mybatis提供了9种动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind。

3)其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。

6、#{}和${}的区别是什么?
1)#{}是预编译处理,${}是字符串替换。

2)Mybatis在处理 #{} 时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

3)Mybatis在处理 ${} 时,就是把${}替换成变量的值。

4)使用#{}可以有效的防止SQL注入,提高系统安全性。
7、为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?

答:Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。

8、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

1)Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

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

9、MyBatis与Hibernate有哪些不同?

1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

2)Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的缺点是学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。

10、MyBatis的好处是什么?

1)MyBatis把sql语句从Java源程序中独立出来,放在单独的XML文件中编写,给程序的维护带来了很大便利。

2)MyBatis封装了底层JDBC API的调用细节,并能自动将结果集转换成Java Bean对象,大大简化了Java数据库编程的重复工作。

3)因为MyBatis需要程序员自己去编写sql语句,程序员可以结合数据库自身的特点灵活控制sql语句,因此能够实现比Hibernate等全自动orm框架更高的查询效率,能够完成复杂查询。

11、简述Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系?
Mybatis将所有Xml配置信息都封装到All-In-One重量级对象Configuration内部。在Xml映射文件中,标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象。标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个