• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

冬日限定

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

第7章 MyBatis的核心配置

学习目标
● 了解MyBatis核心对象的作用
● 熟悉MyBatis配置文件中各个元素的作用
● 掌握MyBatis映射文件中常用元素的使用

7.1 MyBatis的核心对象
SqlSessionFactory
它是单个数据库映射关系经过编译后的内存镜像,其主要作用是创建SqlSession
SqlSessionFactoryBuilder则可以通过XML配置文件或一个预先定义好的Configuration实例构建出SqlSessionFactory的实例
// 读取配置文件 InputStream inputStream = Resources.getResourceAsStream("配置文件位置"); 
// 根据配置文件构建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
线程安全,它一旦被创建,在整个应用执行期间都会存在,多次地创建同一个数据库的SqlSessionFactory,那么此数据库的资源将很容易被耗尽,通常每一个数据库都会只对应一个SqlSessionFactory,使用单例模式
 
SqlSession
它是应用程序与持久层之间执行交互操作的一个单线程对象,其主要作用是执行持久化操作。包含了数据库中所有执行SQL操作的方法,由于其底层封装了JDBC连接,所以可以直接使用其实例来执行已映射的SQL语句。
每一个线程都应该有一个自己的SqlSession实例,并且该实例是不能被共享的。
线程不安全,使用范围最好在一次请求或一个方法中,绝不能将其放在一个类的静态字段、实例字段或任何类型的管理范围(如Servlet的HttpSession)中使用,使用完需及时关闭,通常可以将其放在finally块中关闭
· <T> T selectOne(String statement);返回执行SQL语句查询结果的一条泛型对象。
· <T> T selectOne(String statement, Object parameter);
· <E> List<E> selectList(String statement);
· <E> List<E> selectList(String statement, Object parameter);
· <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);rowBounds是用于分页的参数对象
· void select(String statement, Object parameter,ResultHandler handler);ResultHandler对象用于处理查询返回的复杂结果集,通常用于多表查询
· int insert(String statement);返回执行SQL语句所影响的行数
· int insert(String statement, Object parameter);
· int update(String statement);返回执行SQL语句所影响的行数
· int update(String statement, Object parameter);
· int delete(String statement);返回执行SQL语句所影响的行数。
· int delete(String statement, Object parameter);
· void commit();
· void rollback();
· void close();
· <T> T getMapper(Class<T> type);
· Connection getConnection();获取JDBC数据库连接对象的方法。
工具类
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory = null;
//    初始化sqlsessionfactory对象
    static {
        try{
//            使用mybatis提供的resource类加载mybatis的配置文件
           Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
           
//            构建sqlsession工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        
    }
//    获取sqlsession对象的静态方法
    public static  SqlSession getSession(){
        return sqlSessionFactory.openSession();
    }
}

7.2 配置文件
7.2.1 主要元素
<configuration>元素根元素
<configuration>的子元素必须按照图7-1中由上到下的顺序进行配置,否则MyBatis在解析XML配置文件的时候会报错。
7.2.2 <properties>元素
将内部的配置外在化,即通过外部的配置来动态地替换内部定义的属性。
db.properties配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/spring?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=root
mybatis-config.xm
<properties resource="db.properties" />
<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>
动态替换,为配置提供了诸多灵活的选择。还可以通过配置<properties>元素的子元素<property>,以及通过方法参数传递的方式来获取属性值。实际开发中,使用properties配置文件来配置属性值最常用。
7.2.3 <settings>元素
主要用于改变MyBatis运行时的行为,例如开启二级缓存、开启延迟加载等
<! -- 设置 --> 
<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" /> 
    ... 
</settings>
7.2.4 <typeAliases>元素
为配置文件中的Java类型设置一个简短的名字,即设置别名
<! -- 定义别名 --> 
<typeAliases> 
    <typeAlias alias="user" type="com.itheima.po.User"/> 
</typeAliases>
如果省略alias属性,MyBatis会默认将类名首字母小写后的名称作为别名
当POJO类过多时,还可以通过自动扫描包的形式自定义别名
<! -- 使用自动扫描包来定义别名 --> 
<typeAliases> 
    <package name="com.itheima.po"/> 
</typeAliases>
上述方式的别名只适用于没有使用注解的情况。如果在程序中使用了注解,则别名为其注解的值
@Alias(value = "user") 
public class User { 
    //User的属性和方法 
}
MyBatis框架还默认为许多常见的Java类型(如数值、字符串、日期和集合等)提供了相应的类型别名
别名不区分大小写,所以在使用时要注意重复定义的覆盖问题。
7.2.5 <typeHandler>元素
将预处理语句中传入的参数从javaType(Java类型)转换为jdbcType(JDBC类型),或者从数据库取出结果时将jdbcType转换为javaType。
还可以通过自定义的方式对类型处理器进行扩展(自定义类型处理器可以通过实现TypeHandler接口或者继承BaseTypeHandle类来定义。
1.注册一个类的类型处理器
<typeHandlers> 
<! -- 以单个类的形式配置 --> 
    <typeHandler handler="com.itheima.type.CustomtypeHandler" /> 
</typeHandlers>
2.注册一个包中所有的类型处理器
<typeHandlers> 
<! -- 注册一个包中所有的typeHandler,系统在启动时会自动扫描包下的所有文件,并把它们作为类型处理器。--> 
    <package name="com.itheima.type" /> 
</typeHandlers>
7.2.6 <objectFactory>元素
MyBatis框架每次创建结果对象的新实例时,都会使用一个对象工厂(ObjectFactory)的实例来完成。MyBatis中默认的ObjectFactory(由org.apache.ibatis.reflection.factory.DefaultObjectFactory来提供服务的)的作用就是实例化目标类,它既可以通过默认构造方法实例化,也可以在参数映射存在的时候通过参数构造方法来实例化。
自定义:
(1)自定义一个对象工厂。实现ObjectFactory接口,或者继承DefaultObjectFactory类
// 自定义工厂类 
public class MyObjectFactory extends DefaultObjectFactory { 
    private static final long serialVersionUID = -4114845625429965832L; 
    public <T> T create(Class<T> type) { 
        return super.create(type); 
    } 
    public <T> T create(Class<T> type, List<Class<? >> constructorArgTypes, List<Object> constructorArgs) { 
        return super.create(type, constructorArgTypes, constructorArgs); 
    }
    public void setProperties(Properties properties) { 
        super.setProperties(properties); 
    } 
    public <T> boolean isCollection(Class<T> type) { 
        return Collection.class.isAssignableFrom(type); 
    } 
}
 
(2)在配置文件中使用<objectFactory>元素配置自定义的ObjectFactory
 
<objectFactory type="com.itheima.factory.MyObjectFactory"> 
    <property name="name" value="MyObjectFactory"/> 
</objectFactory>
7.2.7 <plugins>元素
插件。
7.2.8 <environments>元素
实际上就是数据源的配置,我们可以通过<environments>元素配置多种数据源,即配置多种数据库。
<!--default属性,该属性用于指定默认的环境ID-->
<environments default="development"> 
    <environment id="development"> 
    <! -- 使用JDBC事务管理 --> 
    <transactionManager type="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>
在MyBatis中,可以配置两种类型的事务管理器,分别是JDBC和MANAGED。
· JDBC:此配置直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务的作用域。
· MANAGED:此配置从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。在默认情况下,它会关闭连接,但一些容器并不希望这样,为此可以将closeConnection属性设置为false来阻止它默认的关闭行为。
如果项目中使用的是Spring+ MyBatis,则没有必要在MyBatis中配置事务管理器,因为实际开发中,会使用Spring自带的管理器来实现事务管理。
对于数据源的配置,MyBatis框架提供了UNPOOLED、POOLED和JNDI三种数据源类型。
· UNPOOLED
在每次被请求时会打开和关闭连接,适合没有性能要求的简单应用程序。
· POOLED
此数据源利用“池”的概念将JDBC连接对象组织起来,避免了在创建新的连接实例时所需要初始化和认证的时间。这种方式使得并发Web应用可以快速地响应请求,是当前流行的处理方式。
· JNDI
可以在EJB或应用服务器等容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用。
7.2.9 <mappers>元素
指定MyBatis映射文件的位置
1.使用类路径引入
<mappers> <mapper resource="com/itheima/mapper/UserMapper.xml"/> </mappers>
2.使用本地文件路径引入
<mappers> <mapper url="file:///D:/com/itheima/mapper/UserMapper.xml"/> </mappers>
3.使用接口类引入
<mappers> <mapper class="com.itheima.mapper.UserMapper"/> </mappers>
4.使用包名引入
<mappers> <package name="com.itheima.mapper"/> </mappers>
 

7.3 映射文件
7.3.1 主要元素
7.3.2 <select>元素
<select id="findCustomerById" parameterType="Integer" resultType="com.itheima.po.Customer">
    select * from t_customer where id = #{id}
</select>
 
7.3.3 <insert>元素
<insert
    id="addCustomer"
    parameterType="com.itheima.po.Customer"
    flushCache="true"
    statementType="PREPARED"
    keyProperty=""
    keyColumn=""
    useGeneratedKeys=""
    timeout="20">
如果使用的数据库支持主键自动增长(如MySQL),那么可以通过keyProperty属性指定PO类的某个属性接收主键返回值(通常会设置到id属性上),然后将useGeneratedKeys的属性值设置为true
<insert id="addCustomer" parameterType="com.itheima.po.Customer" 
keyProperty="id" useGeneratedKeys="true" > 
    insert into t_customer(username, jobs, phone) 
    values(#{username}, #{jobs}, #{phone}) 
</insert>
如果使用的数据库不支持主键自动增长(如Oracle),或者支持增长的数据库取消了主键自增的规则时,也可以使用MyBatis提供的另一种方式来自定义生成主键,具体配置示例如下。
<insert id="insertCustomer" parameterType="com.itheima.po.Customer"> 
    <selectKey keyProperty="id" resultType="Integer" order="BEFORE"> 
        select if(max(id) is null, 1, max(id) +1) as newId from t_customer 
    </selectKey> 
    insert into t_customer(id, username, jobs, phone) 
    values(#{id}, #{username}, #{jobs}, #{phone}) 
</insert>
<selectKey>元素会首先运行,它会通过自定义的语句来设置数据表中的主键(如果t_customer表中没有记录,则将id设置为1,否则就将id的最大值加1,来作为新的主键),然后再调用插入语句。
<selectKey keyProperty="id" resultType="Integer" order="BEFORE" statementType="PREPARED">
order属性可以被设置为BEFORE或AFTER。如果设置为BEFORE,那么它会首先执行<selectKey>元素中的配置来设置主键,然后执行插入语句;如果设置为AFTER,那么它会先执行插入语句,然后执行<selectKey>元素中的配置内容。
7.3.4 <update>元素和<delete>元素
<update 
    id="updateCustomer" 
    parameterType="com.itheima.po.Customer" 
    flushCache="true" 
    statementType="PREPARED" 
    timeout="20"> 
<delete 
    id="deleteCustomer" 
    parameterType="com.itheima.po.Customer" 
    flushCache="true" 
    statementType="PREPARED" 
    timeout="20">
<! -- 更新信息 --> 
<update id="updateCustomer" parameterType="com.itheima.po.Customer"> 
    update t_customer set username=#{username}, jobs=#{jobs}, phone=#{phone} where id=#{id} 
</update> 
<! -- 删除信息 --> 
<delete id="deleteCustomer" parameterType="Integer"> 
    delete from t_customer where id=#{id} 
</delete>
7.3.5 <sql>元素
定义可重用的SQL代码片段,然后在其他语句中引用这一代码片段
<sql id="customerColumns">id, username, jobs, phone</sql>
<select id="findCustomerById" parameterType="Integer" resultType="com.itheima.po.Customer"> select <include refid="customerColumns"/> from t_customer where id = #{id} </select>
<! --定义表的前缀名 --> 
<sql id="tablename"> 
    ${prefix}customer 
</sql> 
<! --定义要查询的表 --> 
<sql id="someinclude"> 
    from 
    <include refid="${include_target}" /> 
</sql> 
<! --定义查询列 --> 
<sql id="customerColumns"> 
    id, username, jobs, phone 
</sql> 
<! --根据id查询客户信息 --> 
<select id="findCustomerById" parameterType="Integer" resultType="com.itheima.po.Customer"> 
    select 
    <include refid="customerColumns"/> 
    <include refid="someinclude"> 
        <property name="prefix" value="t_" /> 
        <property name="include_target" value="tablename" /> 
    </include> 
    where id = #{id} 
</select>
7.3.6 <resultMap>元素
定义映射规则、级联的更新以及定义类型转化器等。
<! --resultMap的元素结构 --> 
<resultMap type="" id=""> 
    <constructor> <! -- 类在实例化时,用来注入结果到构造方法中--> 
        <idArg/> <! -- ID参数;标记结果作为ID--> 
        <arg/> <! -- 注入到构造方法的一个普通结果--> 
    </constructor> 
    <id/> <! -- 用于表示哪个列是主键--> 
    <result/> <! -- 注入到字段或JavaBean属性的普通结果--> 
    <association property="" /> <! -- 用于一对一关联 --> 
    <collection property="" /> <! -- 用于一对多关联 --> 
处理一个单独的数据库查询返回很多不同数据类型结果集的情况
    <discriminator javaType=""> <! -- 使用结果值来决定使用哪个结果映射--> 
        <case value="" /> <! -- 基于某些值的结果映射 --> 
    </discriminator> 
</resultMap>
案例
1.建表
2.实体类并且实现getter、setter方法和toString
3.mapper
<mapper namespace="com.itheima.po.User">
    <resultMap id="resultMap" type="com.itheima.po.User">
        <id property="id" column="t_id"/>
        <id property="name" column="t_name"/>
        <id property="age" column="t_age"/>
    </resultMap>
    <select id="findAllUser" resultMap="resultMap">
        select *
        from t_user;
    </select>
 
 
</mapper>
4.在配置文件mybatis-config.xml中,引入UserMapper.xml
        <!--    配置Mapper的位置-->
        <mappers>
              <mapper resource="com/itheima/mapper/UserMapper.xml"/>
        </mappers>
5.测试类
    @Test
    public void findAllUserTest()  {
        SqlSession sqlSession = MybatisUtils.getSession();
//        InputStream inputStream = Resources.getResourceAsStream("mybatis-config1.xml");
//        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession.selectList("com.itheima.po.User.findAllUser");
        for(User user : list){
            System.out.println(user);
        }
        sqlSession.close();
    }
Mapped Statements collection does not contain value for com.itheima.mapper.UserMapper.findAllUser
sqlSession.selectList("mapper.namespace + mapper.方法")
Cannot load connection class because of underlying exception: com.mysql.cj.exceptions.WrongArgumentException: Malformed database URL, failed to parse the connection string near ';useSSL=false&amp;serverTimezone=UTC'.
由于使用的是properties配置数据库源,需要把&amp;修改回&
 
getResourceAsReader和getResourceAsStremer的区别?
【思考题】
1.请简述MyBatis核心对象SqlSessionFactory的获取方式。
Resource调用getResourceasStream方法,传入根据mybatis-config.xml配置文件,获取到的值作为 new一个sqlsessionfactorybuilder对象build的方法参数,创建出sqlsessionfactory
2.请简述MyBatis映射文件中的主要元素及其作用。
主要元素
<configuration>
<enviroment>配置运行环境
<mapper>
<select>
……
 

posted on 2023-04-25 01:56  冬日限定  阅读(73)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3