3、配置解析
①、核心配置文件
需要掌握:propertier(属性)、settings(设置)
、typeAliases(类型别名)、environments(环境配置,已写)、mappers(映射器,已写)
②、环境配置environments:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/blog?useSSL=true&usenicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/blog?useSSL=true&usenicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
id 代表这套环境得名字,可以有多套环境,在第一行中得 default,它等于哪个环境的id,用的就是哪套环境。(学会使用多套环境)
transactionManager是事务管理器,主要有两种,一个是JDBC,和managed
dataSource 是数据源,主要的作用是连接数据库,有三种内建数据源类型UNPOOLED, POOLED, JNDI
③、属性 properties
1、可以直接引入外部配置文件,就是在resource目录下,建一个properties文件**(外部配置文件)**,写入连接数据库的相关信息
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/blog?useSSL=true&usenicode=true&characterEncoding=UTF-8
username = root
password = 123456
然后在配置文件中调用这个外部配置文件
<configuration>
<properties resource ="db.properties"/>
<environments default="development">
<environment id="development">
<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>
2、可以在其中增加一些属性配置
3、如果两个文件有同一个字段,优先使用外部配置文件的!
别忘了${}占位符这几句话
④、配置别名优化
起别名的意思就是给java类型设置一个短一点的名字,目的就是为了减少类完全限定名的冗余。
在properties标签后加typealiases标签,有两种标签方法
1、在实体类少的情况下,可以直接给实体类起别名
<typeAliases>
<typeAlias type="com.fu.pojo.User" alias="User"/>
</typeAliases>
2、在实体类多的情况下,可以直接给包起别名,扫描包下所有的类,别名起为这个类的首字母小写的类名
<typeAliases>
<package name = "com.fu.pojo"/>
</typeAliases>
但是,第一种方法的自由度要高一些,可以自定义别名,第二种不行,他默认的别名就是实体类小写的类名,比如我的实体类叫User,别名就默认为user
3、如果用了第二种方法,也可以通过注解的方式强制改掉默认的别名,在实体类上用注解起别名,如下图
@Alias("666") //注解的方式
public class User {
private int id;
private String name;
private int age;
注释的优先级要高于默认实体类的名字
⑤、映射器(Mapper)
注册绑定我们的Mapper文件,一共有四种方式。
方式一:
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="com/fu/dao/UserDao.xml"/>
</mappers>
方式二:用class文件绑定注册
<mappers>
<mapper class="com.fu.dao.UserDao"/>
</mappers>
方式三:
<mappers>
<package name = "com.fu.dao"/>
</mappers>
方式二和方式三的注意点:
- 接口和它的Mapper配置文件必须同名
- 接口和它的Mapper配置文件必须在同一个包下
所以说,规范,最好要让dao包下的UserDao和UserDao.xml放在同一个包下,而且要同名。
⑥、生命周期和作用域
错误的使用会导致并发问题
首先,mybatis的工作流程是先创建一个工具类,去拿到SqlSessionFactoryBuilder,这个SqlSessionFactoryBuilder是为了建造一个工厂,用它来得到SqlSessionFactory,然后去生产SqlSession,最终拿到Sql Mapper,最后结束,流程如下图:
-
SqlSessionFactoryBuilder:
SqlSessionFactoryBuilder的作用只是创建SqlSessionFactory,一旦成功就没用了,所以它的方法范围最好是局部变量。
-
SqlSessionFactory:
比较核心,一旦创建就要一直存在,没有理由丢弃或创建新的对象,类似连接池。最佳作用域是应用作用域,单例或者静态单例,保证全局只有一个变量。
-
SqlSession:
每个线程都要有一个SqlSession实例,类似连接到连接池的一个请求,最佳作用域是放在一个方法里,用完之后关闭,否则资源被占用。
SqlSessionFactoryBuilder,创建SqlSessionFactory,然后SqlSessionFactory一直存在,它根据情况创建出很多SqlSession,每个SqlSession有会有很多Mapper,每个Mapper就是做一个任务,增或删或改或查等等…
⑦、解决属性名和字段名不一致的问题
Ⅰ、问题
实体类的属性名与数据库的字段名不一致,最后的查询结果,就会为空,因为字段名再数据库中找不到,所以他不认识
解决方法:
方式一:起别名(查询A就可以查到age),可起一个让数据库认识的别名,但是太麻烦,不是重点
<select id="select" resultType="user" parameterType="int">
select id,name,A as age from user where id = #{id};
</select>
Ⅱ、resultmap
resultmap是一个结果集映射,首先定义返回类型为resultMap,然后为resultMap起一个名字,然后再查找标签上面设置resultMap,它的id就是resultMap,也就是一个叫resultMap的映射集,type就是返回的类型,下面的例子返回的对象是User(com.fu.pojo.User),然后对应的设置结果,property是实体类的属性名,column为数据库中的字段名。
<resultMap id="UserSelect" type="User">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="A" column="age"/>
</resultMap>
<select id="select" resultMap="UserSelect"> <!-- 首先定义返回值为resultMap,为他起个名字 -->
select * from user where id = #{id};
</select>
单表看着有些鸡肋,但是在多表中有用