mybatis框架

Posted 旺仔的小窝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis框架相关的知识,希望对你有一定的参考价值。

MyBatis介绍

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

1.1 Mybatis架构

1、 mybatis配置

SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sqlid即是Mapped statementid

6、 Mapped Statementsql执行输入参数进行定义,包括HashMap、基本类型、pojoExecutor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7、 Mapped Statementsql执行输出结果进行定义,包括HashMap、基本类型、pojoExecutor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

1.2mybatis jar包

 所需依赖

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.4</version>
</dependency>

1.3 Mybatis入门程序

1.3.1 第一步:创建java工程

使用eclipse创建java工程,jdk使用1.7.0_72

1.3.2 第二步:加入jar

加入mybatis核心包、依赖包、数据驱动包。

1.3.3 第三步:log4j.properties 和 db.properties

log4j.properties 

# Global logging configuration 
# 在实际开发过程中,日志级别要设置成DEBUG,生产环境要设置成info或error
log4j.rootLogger=debug, stdout 
# MyBatis logging configuration... 
log4j.logger.org.mybatis.example.BlogMapper=TRACE 
# Console output... 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

mybatis默认使用log4j作为输出日志信息。

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/数据库名
jdbc.username=root
jdbc.password =****

1.3.4第四步:SqlMapConfig.xml

classpath下创建SqlMapConfig.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>

    <properties resource="db.properties"></properties>
    <!--开启延迟加载放到properties 标签下-->
    <settings>
        <setting name="lazyLoadTriggerMethods" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <!-- SSM   SSH   Spring   MyBatis  Hibernate Struts -->
    <!-- 以后该配置将会配置到Spring内,此处被废弃 -->
    <typeAliases>
        <package name="com.hxzy.myBatis_ehcache"/>
        <!--<typeAlias type="com.hxzy.mybatis.pojo.Users" alias="users"/>-->
        <!--<typeAlias type="com.hxzy.mybatis.pojo.Orders" alias="orders"/>-->
        <!--<typeAlias type="com.hxzy.mybatis.pojo.custom.UsersQueryVo" alias="usersQueryVo"/>-->
        <!--<typeAlias type="com.hxzy.mybatis.pojo.custom.UsersCustom" alias="usersCustom"/>-->
    </typeAliases>
     <!-- 和spring整合后 environments配置将废除-->

    <environments default="developer">
        <environment id="developer">

            <!-- MyBatis的事物的控制 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- MyBatis的数据源 -->
            <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>
    </environments>
    <!--批量配置Mapper接口-->
    <mappers>
        <!--<mapper resource="sqlmap/UserMapper.xml" />-->
        <package name="com.hxzy.myBatis_ehcache.mapper"/>
    </mappers>
</configuration>

settings(配置)

 

SqlMapConfig.xml中配置的内容和顺序如下:

properties(属性)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

自定义别名:

<typeAliases>
    <!-- 单个别名定义 -->
    <typeAlias alias="user" type="cn.atwyl.mybatis.po.User"/>
    <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
    <package name="cn.atwyl.mybatis.po"/>
    <package name="其它包"/>
</typeAliases>

typeHandlers(类型处理器)

<select id="findUserById" parameterType="int" resultType="user">
        select * from user where id = #{id}
</select>

类型处理器

Java类型

JDBC类型

BooleanTypeHandler

Boolean,boolean

任何兼容的布尔值

ByteTypeHandler

Byte,byte

任何兼容的数字或字节类型

ShortTypeHandler

Short,short

任何兼容的数字或短整型

IntegerTypeHandler

Integer,int

任何兼容的数字和整型

LongTypeHandler

Long,long

任何兼容的数字或长整型

FloatTypeHandler

Float,float

任何兼容的数字或单精度浮点型

DoubleTypeHandler

Double,double

任何兼容的数字或双精度浮点型

BigDecimalTypeHandler

BigDecimal

任何兼容的数字或十进制小数类型

StringTypeHandler

String

CHAR和VARCHAR类型

ClobTypeHandler

String

CLOB和LONGVARCHAR类型

NStringTypeHandler

String

NVARCHAR和NCHAR类型

NClobTypeHandler

String

NCLOB类型

ByteArrayTypeHandler

byte[]

任何兼容的字节流类型

BlobTypeHandler

byte[]

BLOB和LONGVARBINARY类型

DateTypeHandler

Date(java.util)

TIMESTAMP类型

DateOnlyTypeHandler

Date(java.util)

DATE类型

TimeOnlyTypeHandler

Date(java.util)

TIME类型

SqlTimestampTypeHandler

Timestamp(java.sql)

TIMESTAMP类型

SqlDateTypeHandler

Date(java.sql)

DATE类型

SqlTimeTypeHandler

Time(java.sql)

TIME类型

ObjectTypeHandler

任意

其他或未指定类型

EnumTypeHandler

Enumeration类型

VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。

 mappers(映射器)

Mapper配置的几种方法:

 <mapper resource=" " />

使用相对于类路径的资源

如:<mapper resource="sqlmap/User.xml" />

 <mapper url=" " />

使用完全限定路径

如:<mapper url="file:///D:\\workspace_spingmvc\\mybatis_01\\config\\sqlmap\\User.xml" />

 <mapper class=" " />

使用mapper接口类路径

如:<mapper class="cn.atwyl.mybatis.mapper.UserMapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

  <package name=""/>

注册指定包下的所有mapper接口

如:<package name="cn.atwyl.mybatis.mapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

1.3.5 第五步:po类

1.3.6 第六步:程序编写

映射文件:

classpath创建映射文件UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
</mapper>

namespace :命名空间 Mapper接口的路径

<!-- 根据id获取用户信息 -->
    <select id="findUserById" parameterType="int" resultType="cn.atwyl.mybatis.po.User">
        select * from user where id = #{id}
    </select>
    <!-- 自定义条件查询用户列表 -->
    <select id="findUserByUsername" parameterType="java.lang.String" 
            resultType="cn.atwyl.mybatis.po.User">
       select * from user where username like \'%${value}%\' 
    </select>

parameterType定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。利用#可以防止Sql注入

resultType:定义结果映射类型。

加载映射文件

mybatis框架需要加载映射文件

<mappers>
        <mapper resource="Mapper配置文件的路径"/>
</mappers>
 测试程序:
public class Mybatis_first {
    
    //会话工厂
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void createSqlSessionFactory() throws IOException {
        // 配置文件
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory
        sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);

    }

    // 根据 id查询用户信息
    @Test
    public void testFindUserById() {
        // 数据库会话实例
        SqlSession sqlSession = null;
        try {
            // 创建数据库会话实例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 查询单个记录,根据用户id查询用户信息
            User user = sqlSession.selectOne("test.findUserById", 10);
            // 输出用户信息
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }

    }

    // 根据用户名称模糊查询用户信息
    @Test
    public void testFindUserByUsername() {
        // 数据库会话实例
        SqlSession sqlSession = null;
        try {
            // 创建数据库会话实例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 查询单个记录,根据用户id查询用户信息
            List<User> list = sqlSession.selectList("test.findUserByUsername", "张");
            System.out.println(list.size());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }

    }
}
 #{}${}

#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value

 parameterTyperesultType

parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。

resultType:指定输出结果类型,mybatissql查询结果的一行记录数据映射为resultType指定类型的对象。

 selectOneselectList

selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

selectList可以查询一条或多条记录。

 添加

<!-- 添加用户 -->
    <insert id="insertUser" parameterType="cn.atwyl.mybatis.po.User">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        select LAST_INSERT_ID() 
    </selectKey>
      insert into user(username,birthday,sex,address) 
      values(#{username},#{birthday},#{sex},#{address})
    </insert>


 <insert id="insertUser" parameterType="User" >
        insert into cocode_member_case
        <trim prefix="(" suffix=")" suffixOverrides="," >
            <if test="caseId != null" >
                case_id,
            </if>
            <if test="memberId != null" >
                member_id,
            </if>
            <if test="caseName != null" >
                case_name,
            </if>
            <if test="remark != null" >
                remark,
            </if>
            <if test="imageUrl != null" >
                image_url,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
            <if test="caseId != null" >
                #{caseId,jdbcType=INTEGER},
            </if>
            <if test="memberId != null" >
                #{memberId,jdbcType=INTEGER},
            </if>
            <if test="caseName != null" >
                #{caseName,jdbcType=VARCHAR},
            </if>
            <if test="remark != null" >
                #{remark,jdbcType=VARCHAR},
            </if>
            <if test="imageUrl != null" >
                #{imageUrl,jdbcType=VARCHAR},
            </if>
        </trim>
    </insert>
测试程序:
// 添加用户信息
    @Test
    public void testInsert() {
        // 数据库会话实例
        SqlSession sqlSession = null;
        try {
            // 创建数据库会话实例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 添加用户信息
            User user = new User();
            user.setUsername("张小明");
            user.setAddress("河南郑州");
            user.setSex("1");
            user.setPrice(1999.9f);
            sqlSession.insert("test.insertUser", user);
            //提交事务
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

mysql自增主键返回

<insert id="insertUser" parameterType="cn.atwyl.mybatis.po.User">
        <!-- selectKey将主键返回,需要再返回 -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
       insert into user(username,birthday,sex,address)
        values(#{username},#{birthday},#{sex},#{address});
    </insert>

添加selectKey实现将主键返回

keyProperty:返回的主键存储在pojo中的哪个属性

orderselectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after

resultType:返回的主键是什么类型

LAST_INSERT_ID():mysql的函数,返回auto_increment自增列新记录id值。

Mysql使用 uuid实现主键

需要增加通过select uuid()得到uuid


<insert  id="insertUser" parameterType="cn.atwyl.mybatis.po.User">
<selectKey resultType="java.lang.String" order="BEFORE" 
keyProperty="id">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address) 
         values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
//注意这里使用的order是“BEFORE”

删除

<!-- 删除用户 -->
    <delete id="deleteUserById" parameterType="int">
        delete from user where id=#{id}
    </delete>

测试程序:

// 根据id删除用户
    @Test
    public void testDelete() {
        // 数据库会话实例
        SqlSession sqlSession = null;
        try {
            // 创建数据库会话实例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 删除用户
            sqlSession.delete("test.deleteUserById",18);
            // 提交事务
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

修改

<!-- 更新用户 -->
    <update id="updateUser"以上是关于mybatis框架的主要内容,如果未能解决你的问题,请参考以下文章

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

Mybatis框架第二篇

markdown [mybatis参考]关于mybatis #mybatis的一些片段

mybatis第二天

MyBatis动态SQL

mybatis学习(39):动态sql片段