mybatis入门篇

基础知识
对原生jdbc程序(单独使用jdbc开发)问题总结
mybatis框架原理
mybatis入门程序(用户的增删改查)
mybatis开发dao两种方法:
    原始dao开发方法(程序需要编写dao接口和实现类)
    mybatis的mapper接口(相当于dao接口)代理开发方法
mybatis配置文件SqlMapConfig.xml
mybatis核心:
    mybatis输入映射
    mybatis输出映射
mybatis的动态sql

高级知识
订单商品数据模型分析
高级结果集映射(一对一、一对多、多对多)
mybatis延迟加载
mybatis查询缓存(一级缓存、二级缓存)
mybatis和spring进行整合
mybatis逆向工程


对原生jdbc程序(单独使用jdbc开发)问题总结
public static void main(String[] args) {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
        String sql = "select * from user where username = ?";
        statement = connection.prepareStatement(sql);
        statement.setString(1, "王五");
        resultSet = statement.executeQuery();
        while(resultSet.next()){
            System.out.println(resultSet.getString("id") + "-" + resultSet.getString("username"));
        }
    } catch (Exception e) {
        
    }finally {
        try {
            if(connection != null){
                connection.close();
            }
            if(statement != null){
                statement.close();
            }
            if(resultSet != null){
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
问题总结
1、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。
设想:使用数据库连接池管理数据库连接
2、将sql语句硬编码到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护
设想:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码重新编译。
3、向prepareStatement中设置参数,对占位符位置和设置参数值,硬编码在java代码中,不利于系统维护
设想:将sql语句及占位符和参数全部设置在xml中
4、从resultSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护
设想:将查询的结果集,自动映射成java对象

mybatis框架
1、SqlMapConfig.xml(是mybatis的全局配置文件),配置了数据源、事务等mybatis运行环境配置映射文件(配置sql语句)
mapper.xml(映射文件)、mapper.xml...
2、SqlSessionFactory(会话工厂)
作用:创建SqlSession
3、SqlSession(会话),是一个接口,面向用户(程序员)的接口
作用:操作数据库(发出sql增删改查)
4、Executor(执行器),是一个接口(基本执行器、缓存执行器)
作用:SqlSession内部通过执行器操作数据库
5、mappedStatement(底层封装对象)
作用:对操作数据库存储封装,包括sql语句,输入参数,输出结果类型
6、输入参数类型:java简单类型、hashmap、pojo自定义
7、输出参数类型:java简单类型、hashmap、pojo自定义

mybatis框架执行过程:
1.配置mybatis的配置文件,sqlMapConfig.xml(名称不固定)
2.通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂
    SqlSessionFactory在实际使用时按单例方式。
3.通过SqlSessionFactory创建SqlSession
    SqlSession是一个面向用户的接口(提供操作数据库方法),实现对象是线程不安全的,建议SqlSession应用场合在方法体内。
4.调用SqlSession的方法去操作数据
    如果需要提交事务,需要执行SqlSession的commit()方法。
5.释放资源,关闭SqlSession.

SqlMapConfig.xml
1.配置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>
    <environments default="development">
        <environment id="development">
        <!-- 使用jdbc事务管理,事务由mybatis控制 -->
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driverClassName" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
</configuration>

查询
1.根据用户id主键查询用户信息
1.pojo类
public class User
 {
    private int id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

2.映射文件(User.xml,mapper代理开发映射文件名称为UserMapper.xml)
在映射文件中配置sql语句
<?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" >

<!-- namespace命名空间,作用就是对sql进行分类管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用
 -->
<mapper namespace="test">

    <!-- 在映射文件中配置很多sql语句 -->
    <!-- 通过select执行数据库查询
    id:标识映射文件的sql,称为statement的id,将语句
    封装到mappedStatement对象中,所以将id称为statement的id
    parameterType:指定參數的類型,这里指定int类型
    #{}表示一个占位符号
    #{id}:其中的id表示接收输入的参数,参数名称就是id,
    如果参数是简单类型,#{}中的参数名可以任意,可以value或其它名称
    resultType指定sql输出结果的所映射的java对象类型,
    select指定resultType表示将单条记录映射成的java对象.
     -->
     <select id="findUserById" parameterType="int">
        select * from user where id = #{value}
     </select>    
</mapper>

#{}和${}
#{}表示一个占位符
${}表示一个拼接符号,会引用sql注入,所以不建议使用

selectOne和selectList
selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。
selectList表示查询出一个表(多条记录)。如果使用selectList查询多条记录,不能使用selectOne。
如果返回多条数据使用selectOne就会报异常
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3

新增一条数据
1.User.xml
<insert id="insertUser" parameterType="cn.chx.mybatis.po.User">
    insert into User(username, birthday, sex, address) values(#{username},
    #{birthday}, #{sex}, #{address})
</insert>

2.测试
// mybatis配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 通过会话工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setSex("0");
user.setAddress("广东省");
user.setBirthday(new Date());
user.setUsername("陈宏鑫");
sqlSession.insert("test.insertUser", user);
// 事务提交
sqlSession.commit();
sqlSession.close();

自增主键返回
mysql自增主键,执行insert提交之前自动生成一个自增主键.
通过mysql函数获取到刚插入记录的自增主键:
LAST_INSERT_ID();是insert之后才调用函数的.

非自增主键返回(使用uuid())
使用mysql的uuid
<!-- 
    使用mysql的uuid()生成主键
    执行过程:
    首先通过uuid()得到主键,将主键设置到User对象的id属性中
    其次在insert执行时,从user对象中取出id属性值
 -->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Integer">
    select uuid()
</selectKey>
insert into User(id, username, birthday, sex, address) values(#{id}, #{username},
#{birthday}, #{sex}, #{address})

mybatis和hibernate本质区别和应用场景
hibernate:是一个标准ORM框架(对象关系映射)。入门门槛高,不需要程序写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难
应用场景:
适用与需求变化不多的中小型项目,比如后台管理系统,erp、orm、oa.

mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全的orm框架,虽然程序员自己写sql,mybatis也可以实现映射(输入映射、输出映射)。
应用场景:
适用与需求变化较多的项目,比如:互联网项目
企业进行技术类型,以低成本高回报作为技术选型的原则,根据项目组的技术力量进行选择。

SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder创建SqlSessionFactory
将SqlSessionFactoryBuilder当成一个工具类使用,不需要使用单例管理SqlSessionFactoryBuilder,在需要创建SqlSessionFactory时候,只需要newy一次SqlSessionFactoryBuilder即可.
SqlSessionFactory
通过SqlSessionFactory创建SqlSession。使用单例模式管理SqlSessionFactory(工厂一旦创建,使用一个实例),将来mybatis和spring整合后,
使用单例模式管理SqlSessionFactory
SqlSession
SqlSession是一个面向用户的接口
SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象),selectList(返回单个或多个对象)
SqlSession是线程不安全的,在SqlSession实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
SqlSession最佳应用场合在方法内,定义局部变量使用。

原始dao开发方法(程序员需要写dao接口和dao实现类)
思路:
程序员需要写dao接口和dao实现类
需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession

dao接口
public interface UserDao {
    User findUserById(Integer id);
    void insertUser(User user);
}

dao接口实现
public class UserDaoImpl implements UserDao {
    private SqlSessionFactory sqlSessionFactory;
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @Override
    public User findUserById(Integer id) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById", id);
        sqlSession.close();
        return user;
    }

    @Override
    public void insertUser(User user) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.insert("test.insertUser", user);
        sqlSession.commit();
        sqlSession.close();
    }

}

测试代码
private UserDaoImpl userDaoImpl;

    @Before
    public void setUp() throws IOException {
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建会话工厂
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        userDaoImpl = new UserDaoImpl(sqlSessionFactory);
    }

    // 根据id查询用户信息,得到一条记录信息
    @Test
    public void findUserByIdTest() throws IOException {
        User user = userDaoImpl.findUserById(1);
        System.out.println(user);
    }
}

总结原始dao开发问题
1.dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量
2.调用SqlSession方法时statement的id硬编码了(spring和mybatis整合后不用写statement的id,可以直接调用)
3.调用SqlSession方法时传入的变量,由于SqlSession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发

mapper代理方法(程序员只需要mapper接口(相当于dao接口))
程序员编写mapper接口(相当于dao接口),程序员还需要编写mapper.xml映射文件,mybatis可以自动生成mapper接口实现类代理对象。
开发规范:
1、在mapper.xml映射文件中namespace等于mapper接口空间地址
<!-- namespace命名空间,作用就是对sql进行分类管理,理解sql隔离 注意:使用mapper代理方法开发,namespace有特殊重要的作用 -->
<mapper namespace="cn.chx.mybatis.mapper.UserMapper">
2、mapper.java接口的方法名和mapper.xml的statement的id一致
3、mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致
4、mapper.java接口中的方法返回类型和mapper.xml中的resultType的类型一致
/**
 * UserMapper
 * mapper接口,相当于dao的接口
 * @author chenhongxin
 *
 */
public interface UserMapper {
    User findUserById(Integer id);
    void insertUser(User user);
}

配置SqlMapConfig.xml加载mapper
    <mapper resource="mapper/UserMapper.xml"/>
</mappers>

测试
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws IOException {
    String resource = "SqlMapConfig.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById(){
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = userMapper.findUserById(1);
    System.out.println(user);
    sqlSession.close();
}

代理对象内部调用selectOne或selectList
如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。
如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。

SqlMapConfig.xml
mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandles(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)

properties
需求:
将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值
在SqlMapConfig.xml中就不需要对数据库参数硬编码。
将数据库连接参数只配置在db.properties中,原因:方便对参数进行统一管理,其它xml可以引用该db.properties
<properties resource="db.properties" />
<environments default="development">
    <environment id="development">
    <!-- 使用jdbc事务管理,事务由mybatis控制 -->
        <transactionManager type="JDBC" />
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driverClass}" />
            <property name="url" value="${jdbc.jdbcUrl}" />
            <property name="username" value="${jdbc.user}" />
            <property name="password" value="${jdbc.password}" />
        </dataSource>
    </environment>
</environments>

注意:MyBatis将按照下面的顺序加载属性
1、在properties元素体内定义的属性首先被读取
2、然后会读取properties元素中resource或url加载的属性,它会覆盖已读取的同名属性
3、最后读取parameterType传递的属性,它会覆盖已读取的同名属性

因此,通过parameterType传递的属性具有最高优先级,resource和url加载的属性次之,最低优先级的是properties元素体内定义的属性.

建议:
不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。
在properties文件中定义属性名要有一定的特殊性,如:属性名.属性名

typeAliases
在mapper.xml中,定义很多statement,statement需要paramterType指定输入参数的类型、需要resultType指定输出结果的映射类型
1.SqlMapConfig.xml配置文件
<typeAliases>
    <!-- 
        批量别名定义
        指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
     -->
    <package name="cn.chx.mybatis.po"/>
</typeAliases>

2.Mapper.xml映射文件
<select id="findUserById" parameterType="int" resultType="User">
    select * from user where id = #{value}
</select>

mappers(映射配置)
1.<mapper resource="mapper/UserMapper.xml"/>
2.<package name="cn.chx.mybatis.mapper"/> // 加载映射文件的包

测试:
public void testFindUserById(){
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = userMapper.findUserById(1);
    System.out.println(user);
    sqlSession.close();
}

输入映射
通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型
6.1.传递pojo的包装对象
    6.1.1.需求
        完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息、其它信息,比如商品、订单)
    6.1.2.定义包装类型pojo
    针对上边的需求,建议使用自定义的包装类型的pojo
    在包装类型的pojo中复杂的查询条件包装进去

/**
 * 用户扩展类
 * @author chenhongxin
 */
public class UserCustomer extends User {

}

public class UserQueryVo {

    // 在这里包装所需要的查询条件

    // 用户查询条件
    private UserCustomer userCustomer;

    public void setUserCustomer(UserCustomer userCustomer) {
        this.userCustomer = userCustomer;
    }

    public UserCustomer getUserCustomer() {
        return userCustomer;
    }

    // 可以包装其它的查询条件,订单、商品
    // ...

}

mapper.xml
在UserMapper.xml中定义用户信息综合查询(查询条件复杂,通过高级查询进行复杂关联查询).
<!-- 用戶信息綜合查詢 -->
<select id="findUserList" parameterType="cn.chx.mybatis.po.UserQueryVo" resultType="cn.chx.mybatis.po.UserCustomer">
    select * from user where user.sex = #{userCustomer.sex} and user.username like '%${userCustomer.username}%'
</select>

mapper.java
List<UserCustomer> findUserList(UserQueryVo userQueryVo);

测试:
    @Test
    public void testFindUserList() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        UserQueryVo userQueryVo = new UserQueryVo();
        UserCustomer user = new UserCustomer();
        user.setSex("1");
        user.setUsername("张三丰");
        userQueryVo.setUserCustomer(user);
        List<UserCustomer> userCustomers = userMapper.findUserList(userQueryVo);
        System.out.println(userCustomers);
        sqlSession.close();
    }

resultType
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象
如果查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象

输出简单类型
    需求
        用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页

mapper.xml
<!-- 用户信息综合查询总数 -->
<select id="findUserCount" parameterType="cn.chx.mybatis.po.UserQueryVo"
    resultType="int">
    select count(*) from user where user.sex =
    #{userCustomer.sex} and
    user.username like '%${userCustomer.username}%'
</select>

mapper.java
int findUserCount(UserQueryVo userQueryVo);

测试:
    @Test
    public void testFindUserCount() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        UserQueryVo userQueryVo = new UserQueryVo();
        UserCustomer user = new UserCustomer();
        user.setSex("1");
        user.setUsername("张三丰");
        userQueryVo.setUserCustomer(user);
        int count = userMapper.findUserCount(userQueryVo);
        System.out.println(count);
        sqlSession.close();
    }

7.2 resultMap使用
mybatis中使用resultMap完成高级输出结果映射

7.2.1 resultMap使用方法
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
1、定义resultMap
2、使用resultMap作为statement的输出映射类型

7.2.2 将下边的sql使用UserCustomer完成映射
select id id_, username _username from user;
userCustomer类中属性名和上边查询列名不一致。

定义resultMap
<!-- 定义resultMap
    select id id_, username _username from user 和User类中的属性作为一个映射关系
    type:resultMap最终映射的java对象类型,可以使用别名
    id:对resultMap的唯一标识
 -->
<resultMap type="user" id="userResultMap">
    <!-- id表示查询结果集中唯一标识
        column:查询出来的列名
        property:type指定的pojo类型中的属性名
        最终resultMap对column和property作为一个映射关系(对应关系)
     -->
     <id property="id" column="id_"/>
     <result property="username" column="_username" />
</resultMap>

<!-- 使用resultMap进行映射
    resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper文件,前边需要加namespace
 -->
<select id="findUserResultMap" resultMap="userResultMap">
    select id id_, username _username from user;
</select>

测试:
    @Test
    public void testFindUserResultMap() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.findUserResultMap();
        System.out.println(users);
        sqlSession.close();
    }

8.动态sql
    8.1.什么是动态sql
    mybatis核心对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装
    8.2.需求
    用户信息综合信息和用户信息查询列表总数这两个statement的定义使用动态sql
    对查询条件进行判断,如果输入不为空,就对sql进行拼接

mapper.xml
<!-- 用戶信息綜合查詢 -->
<select id="findUserList" parameterType="cn.chx.mybatis.po.UserQueryVo"
    resultType="cn.chx.mybatis.po.UserCustomer">
    select * from user
    <!-- where可以自动去掉条件中的第一个and -->
    <where>
        <if test="userCustomer != null">
            <if test="userCustomer.sex != null and userCustomer.sex != ''">
                and user.sex = #{userCustomer.sex}
            </if>
            <if test="userCustomer.username != null and userCustomer.username != ''">
                and user.username like '%${userCustomer.username}%'
            </if>
        </if>
    </where>
</select>

测试代码:
@Test
    public void testFindUserList() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        UserQueryVo userQueryVo = new UserQueryVo();
        UserCustomer user = new UserCustomer();
        user.setSex("1");
        user.setUsername("张三丰");
        userQueryVo.setUserCustomer(user);
        List<UserCustomer> userCustomers = userMapper.findUserList(null); // 如果不设置数据的话就不筛选数据
        System.out.println(userCustomers);
        sqlSession.close();
    }

8.3.sql片段
    8.3.1需求
将上边实现的动态sql判断代码抽取出来,组成一个sql片段。其它的statment中可以引用该sql片段

mapper.xml
定义sql片段
<!-- 
    id:sql片段的唯一标识
    经验:是基于单表来定义sql片段,这样的话这个sql片段可重用性才高
    在sql片段中不要包括where
 -->
<sql id="query_user_where">
    <if test="userCustomer != null">
        <if test="userCustomer.sex != null and userCustomer.sex != ''">
            and user.sex = #{userCustomer.sex}
        </if>
        <if test="userCustomer.username != null and userCustomer.username != ''">
            and user.username like '%${userCustomer.username}%'
        </if>
    </if>
</sql>

引用sql片段
<!-- 用戶信息綜合查詢 -->
<select id="findUserList" parameterType="cn.chx.mybatis.po.UserQueryVo"
    resultType="cn.chx.mybatis.po.UserCustomer">
    select * from user
    <!-- where可以自动去掉条件中的第一个and -->
    <where>
        <include refid="query_user_where" />
    </where>
</select>

9.foreach
向sql传递数组或List,mybatis使用foreach遍历
    
    9.1.需求
在用户查询列表和查询总数的statement中增加多个id输入查询
sql语法如下:
两种方法:
select * from user where id = 1 or id = 10 or id = 16
select * from user where id in(1, 10, 16)

9.2.pojo分装
public class UserQueryVo {

    // 在这里包装所需要的查询条件
    // 传入多个id
    private List<Integer> ids;

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }

9.3.mapper.xml
<if test="ids != null">
    <!-- 使用foreach遍历传入的ids
        collection:指定要遍历的集合属性
        item:遍历生成每个对象
        open:开始遍历拼接的串
        close:结束遍历拼接的串
        separator:遍历的两个对象中需要拼接的串
     -->
    <!-- 第一种方法 -->
    <!-- <foreach collection="ids" item="id" open="and (" close=")" separator="or">
        id=#{id}
    </foreach> -->
    
    <foreach collection="ids" item="id" open="and id in(" close=")" separator=",">
        #{id}
    </foreach>
</if>

测试代码:
@Test
    public void testFindUserList() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        UserQueryVo userQueryVo = new UserQueryVo();
        UserCustomer user = new UserCustomer();
        user.setSex("1");
//      user.setUsername("张三丰");
        List<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        ids.add(10);
        ids.add(16);
        userQueryVo.setIds(ids);
        userQueryVo.setUserCustomer(user);
        List<UserCustomer> userCustomers = userMapper.findUserList(userQueryVo);
        System.out.println(userCustomers);
        sqlSession.close();
    }

mybatis是什么?
mybatis是一个持久层框架,mybatis是一个不完全的ORM框架。sql语句需要程序员自己开发,但是mybatis也有映射(输入映射、输出映射)。
mybatis入门门槛不高,学习成本高,让程序员把精力放在sql语句上,对sql语句优化非常方便,适用与需求变化较多项目,比如互联网项目。
mybatis让程序将主要精力放在sql上,通过mybatis提供的映射放射,自动灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。
mybatis可以将向prepareStatement中的输入参数自动进行输入映射(statement.setString(1, "王五")),将查询结果集灵活映射成java对象(输出映射(resultSet.getString("id")))。

mybatis开发dao的方法:
1.原始dao的方法
    需要程序员编写mapper接口(就是dao接口)
    程序员在编写mapper.xml(映射文件)和mapper.java需要遵循一个开发规范
    1.mapper.xml中namespace就是mapper.java的类全路径
    2.mapper.xml中statement的id和mapper.java中方法名一致
    3.mapper.xml中statement的parameterType指定输入参数的类型和mapper.java的方法输入参数类型一致
    4.mapper.xml中statement的returnType指定输出结果的类型和mapper.java的方法返回类型一致

SqlMapConfig配置文件,可以配置properties属性、别名、mapper加载...

输入映射
parameterType:指定输入参数类型可以简单类型、pojo、hashmap...
对于综合查询,建议parameterType使用包装的pojo,有利于系统扩展

输出映射
resultType:
    查询到的列名和resultType指定的pojo的属性名一致,才能映射成功
resultMap:
    可以通过resultMap完成一些高级映射。
    如果查询到的列名和映射的pojo的属性名不一致时,通过resultMap设置列名和属性名之间的对应关系(映射关系)。可以完成映射。
    高级映射:
        将关联查询的列映射到一个pojo属性中。(一对一)
        将关联查询的列映射到一个list<pojo>中。(一对多)

动态sql:
if判断
where
sql片段

foreach



群号:367159413,欢迎入群

下载地址









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值