MyBatis入门手册
1、JDBC的bug
- 频繁开启关闭数据库,造成数据库资源的浪费(解决方案:使用数据库连接池)
- SQL语句被硬编码到java代码中,如果有一天SQL需要修改,需要重新编译java代码,不利于系统维护(解决方案:将SQL语句放到xml,处理参数在xml中使用占位符进行处理)
- 做查询ResultSet遍历结果集,存在硬编码,不利于系统维护。(解决方案:将查询结果集,自动映射成java对象)
- 处理preparedStatement存在硬编码(解决方案:在xml中处理参数)
2、MyBatis基础名词信息
- SQLMapConfig.xml MyBatis的全局配置文件,名称不固定,在这里配置数据源、事务等信息,(MyBatis运行环境)
- SQLSessionFactory 会话工厂,根据配置创建工厂(创建SQLSession)
- SQLSession 会话 是一个接口面向程序开发人员的接口(操作数据库 发出SQL 进行增删改查)
- Executor 执行器 是一个内部接口(SQLSession内部通过执行器去操作数据库)
- mapped statement 底层封装对象 (对操作数据库存储封装,包括SQL语句 mapper.xml文件中一个Sql对应一个Mapped Statement对象,Sql的id即是Mapped statement的id)输入参数 输出结果
3、MyBatis基础项目创建
-
MyBatis是一个持久层框架,操作数据库时使用的。无需创建JavaWEB项目,建立Java项目即可
-
所需jar包:
- mybatis-3.4.6.jar为核心jar包,必须引入
- lib目录下的jar包为工具包,可有可无
- mysql或oracle数据库的驱动包,必须引入
-
编写db.properties文件
-
配置SQLMapConfig.xml文件
-
创建实体类
-
创建实体类.xml
- namespace 命名空间 对SQL文件进行分类管理起到SQL隔离的作用
- SELECT 封装SQL语句 id就是statement的ID用于标识映射文件的SQL
- parameterType:指定输入参数类型
- resultType: 指定SQL输出结果类型 将输出结果映射到java对象类型(指单条记录的类型)
-
创建操作类
-
加载MyBatis配置文件
Resources.getResourceAsStream(resource);
-
创建SQLSessionFactory
-
创建SQLSession
-
进行增删改查操作(调用SQL语句的方法:命名空间.SQL语句ID)增删改操作要commit()
-
释放资源:close()
-
4、参考配置信息
1、db.properties文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf-8&serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=123456
2、SQLMapConfig.xml:
<?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>
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
</transactionManager>
<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>
<mappers>
<mapper resource="cn/jlc/myBaties/entity/Users.xml"></mapper>
</mappers>
</configuration>
3、实体类.xml:
<?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">
<mapper namespace="entity">
<select id="findOne" resultType="cn.jlc.myBaties.entity.Users" parameterType="int" >
select * from user where id = #{id}
</select>
</mapper>
4、操作类:
public static void main(String[] args) {
String resource = "SQLMapConfig.xml";
try {
//加载MyBatis配置文件
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
//创建SQLSessionFactory
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
//创建SQLSession
SqlSession session = build.openSession();
//进行增删改查操作(调用SQL语句的方法:命名空间.SQL语句ID)
Users o = session.selectOne("entity.findOne", 1);
System.out.println(o);
//释放资源:close()
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
5、#{}和${}区别
#{} 表示一个占位符 #{}接收输入参数
接收简单类型的时候 #{}中可以写成value或者其他名
但是接收实体类型时 通过ognl读取对象中的属性此时#{}中要保证参数名与属性名对照
${} 表示一个拼接符合,会引起SQL注入,所以不建议使用
接收简单类型的时候参数名只能是 v a l u e ,接收实体类型时通过 o g n l 读取对象中的属性此时 {} 接收简单类型的时候参数名只能是value,接收实体类型时 通过ognl读取对象中的属性此时 接收简单类型的时候参数名只能是value,接收实体类型时通过ognl读取对象中的属性此时{}中要保证参数名与属性名对照
6、SelectOne 与SelectList的区别
如果查找到的结果是多个SelectOne会报TooManyResultsException异常
7、MyBatis和Hibernate区别
Hibernate 可以将数据库和java实体类自动映射 不便于操作修改数据,适用于中小型项目
MyBatis需要程序员自己编写SQL语句,便于应对数据的修改,但是也提供了自动化的输入输出映射,适用于复杂的大型项目
8、MyBatis的Dao开发
为什么要进行Dao开发:
- SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
- SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
- SqlSession的实例不能共享使用,它是线程不安全的,每个线程都应该有它自己的SqlSession实例,因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
原始dao编程:
- 创建dao接口与实现类
- 在实现类,定义私有工厂类对象,有参构造与SQL方法
- 有参构造是为了给私有工厂类对象做初始化
- sql方法是利用SQLSession执行SQL操作
- 在调用类,定义初始化方法,在初始化方法中为工厂类对象赋值,定义调用方法
存在的问题:
- 存在大量的模板方法、
- 调用SQLSession方法的时候将statement的id硬编码到了java中
- 调用session方法的时候传入变量,由于底层使用的是泛型,所以即使传入类型错误 在编译阶段也不报错,不利于程序开发
mapper代理模式:
- 创建UserMapper接口 == 实体类名 + Mapper
- 创建mapper.xml(类似于实体类.xml) namespace必须为包名+接口名(对SQL进行分类管理与隔离) id名为接口中对应方法名 参数名要和xml中的参数名对应
- 创建调用类 创建调用方法 创建SQLSession 获取接口实现对象(SQLSession.getMapper)用获取的对象调用接口中的方法
mapper开发规范:
- 在mapper.xml中namespace等于Mapper接口的全限定名
- Mapper接口中的方法名和mapper.xml中statement的id一致
- Mapper接口中的方法输入参数类型和mapper.xml中parameterType指定的类型一致
- Mapper接口中的方法返回值类型和mapper.xml中resultType指定的类型一致