JDBC存在问题
1、在使用JDBC操作数据库前进行连接、操作完成之后关闭连接、并发性能有大的影响
解决:为了达到连接复用,采用连接池
2、SQL语句硬编码在Java代码中,需求改变需要改变Java代码本身
3、返回的结果集也存在硬编码的问题。
MyBatis的介绍
- MyBatis前身ibatis,是Apache旗下的开源的数据持久层框架。
它支持自定义 SQL、存储过程以及高级映射。 - MyBatis免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
- MyBatis可以通过 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain OldJava Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis原理
- 全局配置文件:配置数据源、事务、引入映射文件(mapper1.xml、mapper2.xml…多个,查询SQL、参数类型、结果集的封装)。
- SqlSessionFactory:会话工厂。打开SqlSession。
- SqlSession:会话,操作CRUD。
- Executor:执行器,缓存实现。
- MappedStatement:在配置文件中。
MyBatis的使用Demo
通过实际业务来研究:通过SID查询学生信息
引入依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<!--mybatis配置-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
全局的配置文件(mybatis-config.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>
<!--数据源配置-->
<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/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
POJO类(Student.java)
//数据库中Student表对应的映射Java对象类
public class Student {
private Integer SID;
private String Sname;
private String Ssex;
private Integer Sage;
//省略getter和setter方法
}
Mapper接口文件(StudentMapper.java)
public interface StudentMapper {
/**
* 通过SID查询数据实体
* @param sid
* @return
*/
public Student selectStudentByID(int sid);
}
配置Mapper.xml文件(StudentMapper.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命令空间,随便写,一般保证命名空间唯一 -->
<mapper namespace="com.tulun.MybatisDemo.StudentMapper">
<!--查询标签:select-->
<select id="selectStudentByID" resultType="com.tulun.MybatisDemo.Student">
select * from Student where SID = #{sid}
</select>
</mapper>
修改全局配置文件(mybatis-config.xml)
<!--配置映射-->
<mappers>
<mapper resource="mapper/StudentMapper.xml"/>
</mappers>
执行查询操作
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MybatisTLDemo {
public static void main(String[] args) throws IOException {
//mybatis配置文件
String resource = "mybatis-config.xml";
//通过mybatis提供的Resources类来得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂,传输mybatis配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过反射机制来获取对应mapper实例
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//调用mapper实例下方法
Student student = mapper.selectStudentByID(1);
System.out.println(student);
}
}
步骤总结:
- 配置mybatis-config.xml全局配置文件(数据源、mapper)。
- 创建SqlSessionFactory。
- 通过SqlSessionFactory创建SqlSession对象。
- 通过SqlSession操作数据库CRUD。
添加日志
日志依赖jar包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
日志配置文件
创建log4j.properties文件
## debug 级别
log4j.rootLogger=DEBUG,Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{yyyy-MM-dd-HH\:mm\:ss,SSS} [%t] [%c] [%p] - %m%n
log4j.logger.com.mybatis=DEBUG /
##输出sql 语句
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
日志打印
2020-05-11-10:38:34,366 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@d4004b]
2020-05-11-10:38:34,367 [main] [com.tl.MyBatisDemo.CourseMapper.selectCourseByCourseId] [DEBUG] - ==> Preparing: select * from course where course_id = ?
2020-05-11-10:38:34,388 [main] [com.tl.MyBatisDemo.CourseMapper.selectCourseByCourseId] [DEBUG] - ==> Parameters: 1(Integer)
2020-05-11-10:38:34,405 [main] [com.tl.MyBatisDemo.CourseMapper.selectCourseByCourseId] [DEBUG] - <== Total: 1
配置详解
全局配置文件:Mybatis-config详解
properties:读取外部资源
properties属性可以对外部配置进行动态替换
<!--读取配置,value是默认值-->
<properties resource="db.properties">
<property name="passwd" value="000000"/>
<!--<property name="username" value="123"/>-->
</properties>
配置中的属性可以在整个配置文件中被用来替换需要动态配置的属性值。
<!--数据源配置-->
<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/school"/>
<property name="username" value="${username}"/>
<property name="password" value="${passwd}"/>
</dataSource>
</environment>
</environments>
注意:${passwd}中的passwd要和上面的propertries中的name一致,username也是如此。
如果属性不只一个地方进行配置,mybatis将按照以下的顺序来加载:
- 首先读取在properties元素中指定的属性
- 然后根据properties元素中的resource/url属性指定的文件内容,并覆盖之前读取的同名的属性
- 最后读取作为方法参数传递的属性,并覆盖之前读取的同名属性
通过方法参数传递的属性具有最高优先级,resource或URL加载的属性次之,最低级的是properties元素内的属性。
settings:全局的参数配置
Setting配置参数较多,这里介绍常用的三个参数
cacheEnabled:在Mybatis中耳机缓存的开关,true为开启。
lazyLoadingEnabled和aggressiveLazyEnabled:配置懒加载的开关配置。
<settings>
<!--开启二级缓存开关-->
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
typeAliases:类型别名
类型别名是为java类型设置一个短的名字,和XML配置文件有关,用来减少类完全限定名的冗余。
<typeAliases>
<!--单个别名定义 type:pojo类的路径(全限定名) alias:别名的名称-->
<typeAlias type="com.tl.MyBatisDemo.Course" alias="course"/>
<!--批量别名定义 name:指定的包名,将包下面的所有pojo类取别名 别名默认为类名(首字母大小写都可以)-->
<!--<package name="com.tl.pojo"/>-->
</typeAliases>
在mapper.xml 文件中,定义了很多的Statement,Statement需要parameterType指定输入参数类型,需要resultType指定输出参数类型,如果指定类型为全路径,开发不方便,可以针对parameterType和resultType指定的类型取别名,别名在配置文件(mybatis-config.xml)中配置typeAliases没在mapper.xml文件中使用。
typeHandlers:类型处理器
在进行参数映射成数据库表字段时或者是数据库字段映射成返回java类型时,涉及到类型映射问题,mybatis提供了合适的转换方式,如果不满足需求,可以重写类型处理器。
plugins:插件
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。
environments:环境配置
mybatis可以配置成适应多讴种环境,这种机制有主与SQL映射应用到多种数据库中,如开发,测试,线上环境需要不同的配置。
可以配置多个环境,SQLSessionFactory实例是只能选取其中一种环境。
<!--数据源配置 只加载一个环境,看默认设置-->
<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/school"/>
<property name="username" value="${username}"/>
<property name="password" value="${passwd}"/>
</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/school"/>
<property name="username" value="${username}"/>
<property name="password" value="${passwd}"/>
</dataSource>
</environment>
<environment id="online">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/school"/>
<property name="username" value="${username}"/>
<property name="password" value="${passwd}"/>
</dataSource>
</environment>
</environments>
默认使用的环境 ID(比如:default=“development”)。
每个 environment 元素定义的环境 ID(比如:id=“development”)。
事务管理器的配置(比如:type=“JDBC”)。
数据源的配置(比如:type=“POOLED”)。
mappers:映射器
定义的SQL,需要告诉mybatis到哪里寻找SQL,使用相对类路径的资源引用,有三种映射方式。
<!--配置映射 告诉mybatis SQl语句的位置-->
<mappers>
<!--resource方式:在CourseMapper.xml中定义namespace为mapper接口的地址,映射文件通过namespace来找到mapper接口文件-->
<mapper resource="mapper/CourseMapper.xml"/>
<!--class方式:指定mapper接口的地址遵循规则
将mapper.xml和mapper.java放在同一个目录下,且文件名相同-->
<!--<mapper class="com.tl.MyBatisDemo.CourseMapper"/>-->
<!--package方式:批量的mapper映射需要遵循的规则:将mapper.xml和mapper.java吻技安放在同一个目录且文件名相同-->
<!--<package name="com.tl.MyBatisDemo"/>-->
</mappers>
Mapper XML详解
Mapper XML文件的根标签:mapper,根标签存在属性:namespace(命名空间,一般是接口类的全限定名)
主要介绍增< insert >删< delete >改< update >查< select >标签
select标签
select:查询操作的标签,是一个statement。
id属性(必须):当前命名空间下Statement的唯一标识,要求id和mapper接口中的方法保持一致。
resultType(必须):将结果集映射为Java的对象,该属性值为映射对象的全限定名或者是别名(和resultMap二选一)
resultMap:当数据库的字段和pojo类中的字段不一致的时候,提供的一种结果集映射。
<!--resultMap 标签:处理显性的结果集映射
id(必填):作为结果集的标识
type:指定要映射的Java类型的全限定名
-->
<!--column:数据库字段,property:pojo类中的字段-->
<resultMap id="studentMap" type="com.tl.MyBatisDemo.Course">
<id column="course_name" property="name"/>
</resultMap>
<!--查询标签:select,resultMap和resultType二选一 -->
<select id="selectCourseByCourseId" resultMap="studentMap">
select * from course where course_id = #{cid}
</select>
parameterType(可以忽略):传入参数类型(入参还有parameterMap)
insert 标签
常用属性:
id属性(必须),唯一标识
parameterType(可以忽略)传入参数类型(入参还有parameterMap)
useGeneratedKeys(可以忽略)开启主键回写
update 标签
常用属性:
id属性(必须) 唯一标识
resultType和parameterType(可以忽略)
delete标签
常用属性:
id属性(必须) 唯一标识
resultType和parameterType(可以忽略)
Jnuit测试介绍
Junit是用于编写和运行可重复的自动化测试的开源框架
Junit使用的步骤
引入Junit的依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
生成测试类
- 在Idea下,在需要测试类的当前的窗口,直接快捷点:ctrl+shfit+t ,选择create New Test
- 选择测试类
- 生成测试类
对接口进行测试:
SqlSessionFactory sqlSessionFactory;
SqlSession sqlSession;
@Before
public void before(){
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
Properties properties = new Properties();
properties.setProperty("db.properties","username");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, properties);
}
@After
public void after(){
sqlSession.commit();
sqlSession.close();
}
@Test
public void selectCourseByCourseId() {
常用的注解
@Before
在测试方法之前需要执行一些操作可以放在@Before注解中,例如读取配置信息。
@Test
会被当做测试用例,Junit每一次会创建一个新的测试实例,调用@Test注解方法。
@After
在Test注解调用之后才会执行,一般是进行资源的回收。