Mybatis学习笔记(二)

本文详细介绍了MyBatis的环境配置、事务管理器、数据源的配置,以及属性优化、类型别名、映射器的设置。强调了SqlSessionFactoryBuilder和SqlSessionFactory对象的作用域,推荐使用resource方式引用mapper配置文件。此外,讲解了日志工厂的配置,包括STDOUT_LOGGING和log4j的使用。最后,提到了分页查询和注解开发的实践方法,指出注解适用于简单SQL,复杂SQL则宜采用XML映射。

1.3 配置及优化

环境配置(environments)

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,开发、测试和生产环境需要有不同的配置,不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory实例只能选择一种环境。所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例

事务管理器(transactionManager)

type="[JDBC|MANAGED]",如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为Spring 模块会使用自带的管理器来覆盖前面的配置

数据源(dataSource)

type="[UNPOOLED|POOLED|JNDI]"

1.3.1 配置属性优化

property属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。

编写properties配置文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/xxx?serverTimezone=GMT
username=root
password=root

在主配置文件中引入properties配置文件即可,用 $ 符号引入

<properties resource="db.properties"/>
<environments default="test">
    <environment id="test">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

1.3.2 配置别名优化

类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写

<typeAliases>
    <typeAlias type="com.wlt.domain.User" alias="user"/>
</typeAliases>

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,在没有注解的情况下,会使用Bean 的首字母小写的非限定类名来作为它的别名。

<typeAliases>
    <typeAlias package="com.wlt.domain"/>
</typeAliases>

若有注解,则别名为其注解,例如

@Alias("user")
public class User {
    ...
}

1.3.3 映射器

<!-- 使用相对于类路径的资源引用 -->
<mapper resource="com/wlt/mapper/Mapper.xml"/>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mapper class="com.wlt.mapper.UserMapper"/>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
	<package name="com.wlt.dao"></package>
</mappers>

退荐使用第一种方式 , 即resource,后面springboot和mybatis整合时也常用resource方式来指定mapper配置文件的引用

第二种方式和第三种方式要求接口和其对应的maper文件同名且在同一个包下,否则会报错

1.3.4 作用域和生命周期

作用域和生命周期是至关重要的,错误的使用会造成严重的并发问题

SqlSessionFactoryBuilder对象

<u>该对象的作用在于创建SqlSessionFactory对象,创建成功后就失去作用,所以它只能存在于创建SqlSession对象的方法中,而不能长期存在,因此其最佳作用域为局部变量</u>

SqlSessionFactory对象

相当于一个数据库连接处,其作用在于创建SqlSession接口对象,一旦创建了SqlSessionFactory对象就要长期保存,其生命周期等同于Mybatis的应用周期

SqlSessionFactory是一个对数据库的连接池,占据着数据库的连接资源,如果创建多个对象,那就存在多个数据库连接池,不利于对数据库资源的控制,应尽量避免此情况发生

SqlSessionFactory的最佳作用域为 应用作用域(从Mybatis开始到结束)

SqlSession对象

相当于一个数据库连接(Connection对象),存活在一个业务请求中,处理完请求后需要关闭这条连接(SqlSession.close()),归还到SqlSessionFactory中,否则数据库资源很容易耗费光,系统瘫痪

SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是 请求或方法作用域。

 

1.3.5 设置

mapUnderscoreToCamelCase:是否开启驼峰命名自动映射,即从经典数据库列名A_COLUMN 映射到经典 Java 属性名 aColumn。

 

1.4 ResultMap结果集映射

1.4.1 简单举例:解决数据库字段名和实体类属性名不一致的问题

实体类中的属性为password,而数据库表中的字段为pwd  

/**
     * 通过id查询person表的信息的测试方法
     */
@Test
public void getPersonByIdTest(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
    Person person = mapper.getPersonById(2);
    System.out.println(person);
}

查询出的结果为:

可以看到查出的数据中实体类的 password属性为null,因为mybatis没有从数据库中找到对应的字段名

解决方法:使用resultMap结果集映射

select标签中的resultMap应与resultMap标签的id值想同

resultMap中的type标签为返回的实体类,result标签中的column对应表中的字段名,而property对应实体类中的属性名

<mapper namespace="com.wlt.mapper.PersonMapper">
    <resultMap id="personMap" type="com.wlt.domain.Person">
        <result column="pwd" property="password"></result>
    </resultMap>
    <select id="getPersonById" resultMap="personMap">
        select * from person where id=#{id};
    </select>
</mapper>

重新进行测试后可得:

1.5 日志工厂

1.5.1 标准的日志工厂 STDOUT_LOGGING

    <settings>
        <!--标准的日志实现,不需要导包,可直接使用-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

 在控制台打印出的日志信息

 

1.5.2 log4j日志

  • 在pom.xml中导入log4j的依赖

<!--        导入log4j的依赖-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

在resources资源下编写log4j.properties配置文件

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/wlt.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  • 使用log4j的类

//导包
import org.apache.log4j.Logger;
//创建logger对象
static Logger logger = Logger.getLogger(UserTest.class);

//logger的三个方法
logger.info()
logger.error()
logger.debug()

1.6 分页查询功能

1.6.1 利用limit进行分页,map集合传参

   /**
     * 分页查询
     * @param map
     *
     * @return
     */
    List<Person> findPersonByPage(Map<String,Object> map);
    <select id="findPersonByPage" resultMap="personMap" parameterType="map">
        select * from person limit #{startIndex},#{pageSize};
    </select>
/**
     * 分页查询的测试方法
     */
    @Test
    public void findPersonByPageTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("startIndex",1);
        map.put("pageSize",3);
        List<Person> person = mapper.findPersonByPage(map);
        for (Person pr : person) {
            System.out.println(pr);
        }
        sqlSession.close();
    }

1.7 使用注解开发(简单的sql语句可以使用注解,但对于复杂的sql语句使用xml来进行编写,方便后期的维护)

直接在接口上添加注解后再编写sql语句

使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句

接口方法中传入参数为基本类型或者String类型时需要添加注解@Param()

sql语句中引用的就是@Param()注解中的属性名

  /**
     * 查询所有信息
     * @return
     */
    @Select("select * from person")
    List<Person> findAllPerson();

    /**
     * 通过id查询信息
     * @param id
     * @return
     */
    @Select("select * from person where id=#{id}")
    Person findPersonById(@Param("id") int id);

    /**
     * 增加用户
     * @param person
     */
    @Insert("insert into person (name,pwd)values(#{name},#{password})")
    void insertPerson(Person person);

    /**
     * 通过id删除信息
     * @param id
     */
    @Delete("delete from person where id=#{id}")
    void deletePersonById(@Param("id") int id);


    /**
     * 通过id修改信息
     * @param person
     */
    @Update("update person set name=#{name},pwd=#{password} where id=#{id}")
    void updatePersonById(Person person);
 /**
     * 使用注解测试查询所有信息
     */
    @Test
    public void findAllPersonTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);

        List<Person> allPerson = mapper.findAllPerson();
        for (Person person : allPerson) {
            System.out.println(person);
        }
        sqlSession.close();

    }

    /**
     * 使用注解测试通过id查询信息
     */
    @Test
    public void findPersonByIdTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        Person person = mapper.findPersonById(2);
        System.out.println(person);
        sqlSession.close();
    }

    /**
     * 使用注解测试增加用户
     */
    @Test
    public void insertPersonTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        mapper.insertPerson(new Person("悦湖","152400"));
        sqlSession.close();
    }

    /**
     * 使用注解测试修改用户信息
     */
    @Test
    public void updatePersonTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        mapper.updatePersonById(new Person("小费","0303",6));
        sqlSession.close();
    }

    /**
     * 使用注解测试删除用户信息
     */
    @Test
    public void deletePersonByIdTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        mapper.deletePersonById(6);
        sqlSession.close();
    }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值