myBatis笔记

时间:2022-07-24
本文章向大家介绍myBatis笔记,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、 MyBatis介绍

序号

Mybatis

hibernate

iBatis SSI 2002年诞生 Cliton begin

2001年 Given King

2010年5月由apache投奔google

Jboss,apache

基于SQL 面向结果集

基于面向对象 HQL

效率高

效率低

SqlSessionFactory

SessionFactory

SqlSession

Session

sqlMapConfig.xml

Hibernate.cfg.xml

userMapper.xml

映射文件 user.hbm.xml

Hibernate面向对象,它使用HQL,可以无需写SQL语句。全自动ORM。

Mybatis面向对象,它使用SQL语句,很依赖于SQL语句。半自动ORM。

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对象,sql的id即是Mapped statement的id。

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

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

二、 体验Mybatis

1. 创建一个java工程

使用eclipse创建java工程,jdk使用1.6。

2. 导入jar

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

3. log4j.properties

在classpath下创建log4j.properties如下:

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# 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作为输出日志信息。

4. SqlMapConfig.xml

在classpath下创建SqlMapConfig.xml,如下:

<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEconfiguration
PUBLIC"-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--<properties resource=""></properties> -->
    <environmentsdefault="development">
        <environmentid="development">
            <transactionManagertype="JDBC"/>
            <dataSourcetype="POOLED">
                <propertyname="driver"value="com.mysql.jdbc.Driver"/>
                <propertyname="url"value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
                <propertyname="username"value="root"/>
                <propertyname="password"value="mysql"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。

5. po类

Po类作为mybatis进行sql映射使用,po类通常与数据库表对应,User.java如下:

publicclass User {
    private int id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 出生日期
    private String address;// 地址
    private String detail;// 详细信息
    private Float score;// 成绩
get/set……

6.sql映射文件

在classpath下的sqlmap目录下创建sql映射文件User.xml:

<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEmapper
PUBLIC"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="test">
<!--根据id获取用户信息 -->
    <selectid="selectUserById" parameterType="int"resultType="cn.itcast.mybatis.po.User">
        select * from user where id = #{id}
    </select>
    <!--获取用户列表 -->
    <selectid="selectUserList" resultType="cn.itcast.mybatis.po.User">
        select * from user 
    </select>
    <!--添加用戶 -->
    <insertid="insertUser" parameterType="cn.itcast.mybatis.po.User">
    insert into user(username,birthday,sex,address,detail,score)
        values(#{username},#{birthday},#{sex},#{address},#{detail},#{score})
    </insert>
    <!--更新用戶 -->
    <updateid="updateUser" parameterType="cn.itcast.mybatis.po.User">
       update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address},detail=#{detail},score=#{score} 
    where id=#{id}
    </update>
    <!--刪除用戶 -->
    <deleteid="deleteUser" parameterType="cn.itcast.mybatis.po.User">
    delete from user where id=#{id}
    </delete>
</mapper>

namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。

parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。id是实体类的属性名

resultType:定义结果映射类型。

7.将User.xml添加在SqlMapConfig.xml

在SqlMapConfig.xml中添加mappers如下:

<mappers>
        <mapperresource="sqlmap/user.xml"/>
</mappers>

这里即告诉mybatis Sql映射文件在哪里。

8.程序编写

查询

/**
 * 第一个mybatis程序
 * 
 * @authorThinkpad
 * 
 */
publicclass Mybatis_select {
    publicstaticvoid main(String[] args) throws IOException {
        //mybatis配置文件
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //使用SqlSessionFactoryBuilder创建sessionFactory
        SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder()
                .build(inputStream);
        //通过session工厂获取一个Sqlsession,sqlsession中包括了对数据库操作的sql方法
        SqlSession session = sqlSessionFactory.openSession();
        try {
            //通过sqlsession调用selectOne方法获取一条结果集
            //参数1:指定定义的statement的id,参数2:指定向statement中传递的参数
            User user = session.selectOne("test.selectUserById", 1);
            System.out.println(user);
        } finally{
            session.close();
        }

    }
}

添加

public class Mybatis_insert {
    publicstaticvoid main(String[] args) throws IOException {
        //mybatis配置文件
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //使用SqlSessionFactoryBuilder创建sessionFactory
        SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder()
                .build(inputStream);
        //通过session工厂获取一个Sqlsession,sqlsession中包括了对数据库操作的sql方法
        SqlSession session = sqlSessionFactory.openSession();
        try {
            User user = newUser();
            user.setUsername("张三");
            user.setBirthday(new Date());
            user.setSex("1");
            user.setAddress("北京市");
            user.setDetail("好同志");
            user.setScore(99.8f);
            session.insert("test.insertUser", user);
            session.commit();
        } finally{
            session.close();
        }

    }
}

主键返回

通过修改sql映射文件,可以将mysql自增主键返回:

<insert id="insertUser"parameterType="cn.itcast.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,detail,score)
        values(#{username},#{birthday},#{sex},#{address},#{detail},#{score});
    </insert>

添加selectKey实现将主键返回

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

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

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

LAST_INSERT_ID():是mysql的函数

Oracle可采用序列完成:

首先自定义一个序列且于生成主键,selectKey使用如下:

<selectKey resultType="java.lang.Integer" order="BEFORE"

keyProperty="id">

SELECT 自定义序列.NEXTVAL FROM DUAL

</selectKey>

注意这里使用的order是“BEFORE”

删除

public class Mybatis_delete {
    publicstaticvoid main(String[] args) throws IOException {
        //mybatis配置文件
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //使用SqlSessionFactoryBuilder创建sessionFactory
        SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder()
                .build(inputStream);
        //通过session工厂获取一个Sqlsession,sqlsession中包括了对数据库操作的sql方法
        SqlSession session = sqlSessionFactory.openSession();
        try {
            session.delete("test.deleteUser", 4);
            session.commit();
        } finally{
            session.close();
        }

    }
}

修改

public class Mybatis_update {
    public static void main(String[] args) throws IOException {
        //mybatis配置文件
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //使用SqlSessionFactoryBuilder创建sessionFactory
        SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder()
                .build(inputStream);
        //通过session工厂获取一个Sqlsession,sqlsession中包括了对数据库操作的sql方法
        SqlSession session = sqlSessionFactory.openSession();
        try {
            User user = newUser();
            user.setId(4);
            user.setUsername("李四");
            user.setBirthday(new Date());
            user.setSex("1");
            user.setAddress("北京市");
            user.setDetail("好同志");
            user.setScore(99.8f);
            session.update("test.updateUser", user);
            session.commit();
        } finally{
            session.close();
        }

    }
}

三、Namespace的作用(重要)

命名空间除了对sql进行隔离,mybatis中对命名空间有特殊的作用,用于定义mapper接口地址。

问题:

没有使用接口编程,java是面向接口编程语言,对数据库的操作应该定义一些操作接口,如:用户添加、用户删除、用户查询等,调用dao接口完成数据库操作。

解决:

public interface UserDao {
    public User getUserById(int id) throws Exception;
    public void insertUser(User user) throws Exception;
}
public class UserDaoImpl implements UserDao {
    
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
        this.setSqlSessionFactory(sqlSessionFactory);
    }
    
    private SqlSessionFactory sqlSessionFactory;
    @Override
    public User getUserById(int id) throws Exception {
        SqlSession session = sqlSessionFactory.openSession();
        User user = null;
        try {
            //通过sqlsession调用selectOne方法获取一条结果集
            //参数1:指定定义的statement的id,参数2:指定向statement中传递的参数
            user = session.selectOne("selectUserById", 1);
            System.out.println(user);
            //获取List
            List<User> list = session.selectList("selectUserList");
            System.out.println(list);
            
        } finally{
            session.close();
        }
        return user;
    }
    
    @Override
    publicvoid insertUser(User user) throws Exception {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            session.insert("insertUser", user);
            session.commit();
        } finally{
            session.close();
        }
        
    }
    public SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }
    publicvoid setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
}

问题:

第一个例子中,在访问sql映射文件中定义的sql时需要调用sqlSession的selectOne方法,并将sql的位置(命名空间+id)和参数传递到selectOne方法中,且第一个参数是一个长长的字符串,第二个参数是一个object对象,这对于程序编写有很大的不方便,很多问题无法在编译阶段发现。

虽然上边对提出的面向接口编程问题进行解决,但是dao实现方法中仍然是调用sqlSession的selectOne方法,重复代码多。

改为mapper 接口实现:

第一步:定义mapper.xml

Mapper.xml文件不变还用原来的。

第二步:定义mapper 接口

/**
 * 用户管理mapper
 * @authorThinkpad
 *
 */
public interface UserMapper {
    public User selectUserById(int id) throws Exception;
public List<User> selectUserList() throws Exception;
public void insertUser(User user) throws Exception;
    public void updateUser(User user) throws Exception;
public voiddeleteUser(int id) throws Exception;
}

接口定义有如下特点:

1、 Mapper接口方法名和mapper.xml中定义的每个sql的id相同

2、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

3、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

第三步:修改namespace

Mapper.xml映射文件中的namepace改为如下:

<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">

修改后namespace即是mapper接口的地址。

第四步:通过mapper接口调用statement

public class UserMapperTest extends TestCase {

    private SqlSessionFactory sqlSessionFactory;
    
    protected void setUp() throws Exception {
        //mybatis配置文件
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //使用SqlSessionFactoryBuilder创建sessionFactory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    
    public void testSelectUserById() throws Exception {
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获取mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //通过mapper接口调用statement
        User user = userMapper.selectUserById(1);
        System.out.println(user);
        //关闭session
        session.close();
        
    }
public void testSelectUserList() throws Exception {
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获取mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //通过mapper接口调用statement
        List<User>list = userMapper.selectUserList();
        System.out.println(list);
        //关闭session
        session.close();
        
    }
public void testInsertUser() throws Exception {
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //要添加的数据
        User user = newUser();
        user.setUsername("张三");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("北京市");
        user.setDetail("好同志");
        user.setScore(99.8f);
        //通过mapper接口添加用户
        userMapper.insertUser(user);
        //提交
        session.commit();
        //关闭session
        session.close();
    }
    public void testUpdateUser() throws Exception {
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //要更新的数据
        User user = newUser();
        user.setId(7);
        user.setUsername("李四");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("北京市");
        user.setDetail("好同志");
        user.setScore(99.8f);
        //通过mapper接口调用statement
        userMapper.updateUser(user);
        //提交
        session.commit();
        //关闭session
        session.close();
    }
    public void testDeleteUser() throws Exception {
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //通过mapper接口删除用户
        userMapper.deleteUser(6);
        //提交
        session.commit();
        //关闭session
        session.close();
    }

}

session.getMapper(UserMapper.class)生成一个代理对象作为UserMapper的接口实现对象。

总结:

使用mapper接口不用写接口实现类即可完成数据库操作,简单方便,此方法为官方推荐方法。

使用mapper接口调用必须具备如下条件:

1、 Mapper接口方法名和mapper.xml中定义的每个sql的id相同

2、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

3、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

4、 Mapper.xml文件中的namespace即是mapper接口的类路径。

至此,mybatis的mapper包括mapper.xml和mapper接口两种文件。

四、SqlMapConfig.xml

配置内容

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

properties(属性)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

properties(属性)

SqlMapConfig.xml可以引用java属性文件中的配置信息如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=mysql

SqlMapConfig.xml引用如下:

<properties resource="db.properties"/>
    <environments default="development">
        <environment id="development">
            <transaction Managertype="JDBC"/>
            <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>

typeAliases(类型别名)

mybatis支持别名:

别名

映射的类型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

自定义别名:

在SqlMapConfig.xml中配置:
<typeAliases>
    <!--单个别名定义 -->
    <typeAlias alias="user" type="cn.itcast.mybatis.po.User"/>
    <!--批量别名定义,扫描整个包下的类 别名默认为类名首字母小写-->
    <package name="cn.itcast.mybatis.po"/>
</typeAliases>

typeHandlers(类型处理器)

类型处理器在将java类型和sql映射文件进行映射时使用,如下:

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

parameterType:指定输入数据类型为int,即向statement设置值

resultType:指定输出数据类型为自定义User,即将resultset转为java对象

mybatis自带的类型处理器基本上满足日常需求,不需要单独定义。

mybatis支持类型处理器:

类型处理器

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_spingmvcmybatis_01configsqlmapuser.xml" />

<mapper class=" " />

使用mapper接口类路径

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

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

<package name=""/>

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

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

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

五、 Mapper.xml

Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。

#{}与${}

#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?。

<!--根据id查询用户信息 -->
    <select id="selectUserById" parameterType="int" resultType="user">
        select * from user where id = #{id}
    </select>

使用占位符#{}可以有效防止sql注入,在使用时不需要关心参数值的类型,mybatis会根据参数值的类型调用不同的statement设置参数值的方法。可以想象为:如果参数值是一个字符串则自动映射生成的sql中参数值两边自动有单引号,如果参数值是一个数字型则自动映射生成的sql中参数值两边没有单引号。

注意:当传递单个值时#{}中的参数名称通常和mapper接口的形参名称相同,也可以设置成任意值。

${}和#{}不同,${}是将参数值不加修饰的拼在sql中,相当中用jdbc的statement拼接sql,使用${}不能防止sql注入,但是有时用${}会非常方便,如下的例子:

<!--根据名称模糊查询用户信息 -->
    <select id="selectUserByName" parameterType="string" resultType="user">
    select * from user where username like '%${value}%'
    </select>

如果本例子使用#{}则传入的字符串中必须有%号,而%是人为拼接在参数中,显然有点麻烦,如果采用${}在sql中拼接为%的方式则在调用mapper接口传递参数就方便很多。

再比如order by排序,如果将列名通过参数传入sql,根据传的列名进行排序,应该写为:

ORDER BY ${columnName}

如果使用#{}将无法实现此功能。

注意:{}不能防止sql注入,对系统安全性有很大的影响,如果使用{}建议传入参数尽量不让用户自动填写,即使要用户填写也要对填写的数据进行校验,保证安全性。

另外,当传递单个值时${}中填写的参数名称经过测试填写value不报错。

动态sql(重点)

Mybatis提供使用ognl表达式动态生成sql的功能。

If

<!--传递pojo综合查询用户信息 -->
    <select id="selectUserByUser" parameterType="user" resultType="user">
        select * from user 
        where 1=1 
        <if test="id!=null and id!=''">
        and id=#{id}
        </if>
        <if test="username!=null and username!=''">
        and username like '%${username}%'
        </if>
    </select>

注意要做不等于空字符串校验。

Where

上边的sql也可以改为:

<select id="selectUserByUser" parameterType="user" resultType="user">
        select * from user 
        <where>
        <if test="id!=null and id!=''">
        and id=#{id}
        </if>
        <if test="username!=null and username!=''">
        and username like '%${username}%'
        </if>
        </where>
    </select>

<where />可以自动处理第一个and。

foreach

向sql传递数组或List,mybatis使用foreach解析,如下:

传递List

传递List类型在编写mapper.xml没有区别,唯一不同的是只有一个List参数时它的参数名为list。

如下:

<select id="selectUserByList" parameterType="java.util.List"resultType="user">
        select * from user 
        <where>
        <!--传递List,List中是pojo -->
        <if test="list!=null">
        <foreach collection="list" item="item" open="and id in(" separator="," close=")">
        #{item.id} 
        </foreach>
        </if>
        </where>
    </select>
传递数组(数组中是pojo):
<!--传递数组综合查询用户信息 -->
    <select id="selectUserByArray" parameterType="Object[]" resultType="user">
        select * from user 
        <where>
        <!--传递数组 -->
        <if test="array!=null">
        <foreach collection="array" index="index" item="item" open="and id in(" separator="," close=")">
        #{item.id} 
        </foreach>
        </if>
        </where>
    </select>

sql只接收一个数组参数,这时sql解析参数的名称mybatis固定为array,如果数组是通过一个pojo传递到sql则参数的名称为pojo中的属性名。

index:为数组的下标。

item:为数组每个元素的名称,名称随意定义

open:循环开始

close:循环结束

separator:中间分隔输出

如果数组中是简单类型则写为#{item},不用再通过ognl获取对象属性值了。

Sql片段

需求

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的,如下:

<!--传递pojo综合查询用户信息 -->
    <select id="selectUserByUser" parameterType="user" resultType="user">
        select * from user 
        <where>
        <if test="id!=null and id!=''">
        and id=#{id}
        </if>
        <if test="username!=null and username!=''">
        and username like '%${username}%'
        </if>
        </where>
    </select>

将where条件抽取出来:

<sql id="query_user_where">
    <if test="id!=null and id!=''">
        and id=#{id}
    </if>
    <if test="username!=null and username!=''">
        and username like '%${username}%'
    </if>
</sql>

使用include引用:

<select id="selectUserByUser" parameterType="user" resultType="user">
        select * from user 
        <where>
        <include refid="query_user_where"/>
        </where>
    </select>

注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:

<include refid="namespace.sql片段”/>

resultMap

当输出pojo的字段和sql查询出来的字段名称不对应时而还想用这个pojo类作为输出类型这时就需要使用resultMap了。

另外,resultMap也解决了一对一关联查询、一对多关联查询等常见需求。

创建Person类'

Public class Person {
    privateint id;
    private String name;// 用户姓名,名称和User表的字段名称不一样
    private String sex;// 性别
    private Date birthday;// 出生日期
    private String addr;// 地址,名称和User表的字段名称不一样
    private String detail;// 详细信息
    private Float score;// 成绩
get/set。。。。

定义resultMap

在mapper.xml文件中定义resultMap:

<!-- resultMap定义 -->
<resultMap type="cn.itcast.mybatis.po.Person" id="personmap">
<id property="id" column="id"/>
<result property="name" column="username"/>
<result property="addr" column="address"/>
</resultMap>

<id />:此属性表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个<id />。

Property:表示person类的属性。

Column:表示sql查询出来的字段名。

Column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。

<result />:普通结果,即pojo的属性。

这里只将sql查询出来的字段与pojo属性名不一致的进行了定义,通过后边的测试pojo属性名和sql字段相同的自动进行映射。

Mapper.xml定义

<!--获取用户列表返回resultMap -->
    <select id="selectUserListResultMap" resultMap="personmap">
        select * from user
    </select>

使用resultMap指定上边定义的personmap。

Mapper接口定义

public List<Person> selectUserListResultMap() throws Exception;

实际返回的类型是Person类型。

测试:

Public void testselectUserListResultMap() throws Exception{
        //获取session
        SqlSession session = sqlSessionFactory.openSession();
        //获限mapper接口实例
        UserMapper userMapper = session.getMapper(UserMapper.class);
    
        User user = newUser();
        user.setUsername("管理员");

        //查询用户列表返回resultMap
        List<Person> list = userMapper.selectUserListResultMap();
        System.out.println(list);
        //关闭session
        session.close();
    }