1、数据库操作框架的历程
(1) JDBC
JDBC(Java Data Base Connection,java 数据库连贯) 是一种用于执行 SQL 语句的 Java API, 能够为多种关系数据库提供对立拜访, 它由一组用 Java 语言编写的类和接口组成.JDBC 提供了一种基准, 据此能够构建更高级的工具和接口, 使数据库开发人员可能编写数据库应用程序
- 长处:运行期:快捷、高效
-
毛病:编辑期:代码量大、繁琐异样解决、不反对数据库跨平台
(2) DBUtils
DBUtils 是 Java 编程中的数据库操作实用工具,玲珑简略实用。
DBUtils 封装了对 JDBC 的操作,简化了 JDBC 操作,能够少写代码。
DBUtils 三个外围性能介绍
1、QueryRunner 中提供对 sql 语句操作的 API
2、ResultSetHandler 接口,用于定义 select 操作后,怎么封装后果集
3、DBUtils 类,它就是一个工具类,定义了敞开资源与事务处理的办法
(3)Hibernate
Hibernate 是由 Gavin King 于 2001 年创立的凋谢源代码的对象关系框架。它弱小且高效的构建具备关系对象持久性和查问服务的 Java 应用程序。
Hibernate 将 Java 类映射到数据库表中,从 Java 数据类型中映射到 SQL 数据类型中,并把开发人员从 95% 的公共数据持续性编程工作中解放出来。
Hibernate 是传统 Java 对象和数据库服务器之间的桥梁,用来解决基于 O/R 映射机
Hibernate 劣势
- Hibernate 应用 XML 文件来解决映射 Java 类别到数据库表格中,并且不必编写任何代码。
- 为在数据库中间接贮存和检索 Java 对象提供简略的 APIs。
- 如果在数据库中或任何其它表格中呈现变动,那么仅须要扭转 XML 文件属性。
- 形象不相熟的 SQL 类型,并为咱们提供工作中所相熟的 Java 对象。
- Hibernate 不须要应用程序服务器来操作。
- 操控你数据库中对象简单的关联。
- 最小化与拜访数据库的智能提取策略。
-
提供简略的数据询问。
Hibernate 劣势
- hibernate 的齐全封装导致无奈应用数据的一些性能。
- Hibernate 的缓存问题。
- Hibernate 对于代码的耦合度太高。
- Hibernate 寻找 bug 艰难。
-
Hibernate 批量数据操作须要大量的内存空间而且执行过程中须要的对象太多
(4) JDBCTemplate
JdbcTemplate 针对数据查问提供了多个重载的模板办法, 你能够依据须要选用不同的模板办法. 如果你的查问很简略,仅仅是传入相应 SQL 或者相干参数,而后获得一个繁多的后果,那么你能够抉择如下一组便当的模板办法。
长处:运行期:高效、内嵌 Spring 框架中、反对基于 AOP 的申明式事务
毛病:必须于 Spring 框架联合在一起应用、不反对数据库跨平台、默认没有缓存
2、什么是 Mybatis?
MyBatis 是一款优良的长久层框架,它反对自定义 SQL、存储过程以及高级映射。MyBatis 罢黜了简直所有的 JDBC 代码以及设置参数和获取后果集的工作。MyBatis 能够通过简略的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,一般老式 Java 对象)为数据库中的记录。
长处:
1、与 JDBC 相比,缩小了 50% 的代码量
2、最简略的长久化框架,简略易学
3、SQL 代码从程序代码中彻底分离出来,能够重用
4、提供 XML 标签,反对编写动静 SQL
5、提供映射标签,反对对象与数据库的 ORM 字段关系映射
毛病:
1、SQL 语句编写工作量大,熟练度要高
2、数据库移植性比拟差,如果须要切换数据库的话,SQL 语句会有很大的差别
3、第一个 Mybatis 我的项目
1、创立一般的 maven 我的项目
2、导入相干的依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mashibing</groupId>
<artifactId>mybatis_helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
3、创立对应的数据表
CREATE TABLE `demo`.`Untitled` (`empno` int(4) NOT NULL,
`ename` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`job` varchar(9) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`mgr` int(4) NULL DEFAULT NULL,
`hiredate` date NULL DEFAULT NULL,
`sal` int(11) NULL DEFAULT NULL,
`comm` int(11) NULL DEFAULT NULL,
`deptno` int(11) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `emp` VALUES (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, NULL, 20);
INSERT INTO `emp` VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);
INSERT INTO `emp` VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);
INSERT INTO `emp` VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, NULL, 20);
INSERT INTO `emp` VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);
INSERT INTO `emp` VALUES (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, NULL, 30);
INSERT INTO `emp` VALUES (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, NULL, 10);
INSERT INTO `emp` VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, NULL, 20);
INSERT INTO `emp` VALUES (7839, 'KING', 'PRESIDENT', NULL, '1981-11-17', 5000, NULL, 10);
INSERT INTO `emp` VALUES (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500, 0, 30);
INSERT INTO `emp` VALUES (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, NULL, 20);
INSERT INTO `emp` VALUES (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, NULL, 30);
INSERT INTO `emp` VALUES (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, NULL, 20);
INSERT INTO `emp` VALUES (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, NULL, 10);
4、创立与表对应的实体类对象
emp.java
package com.mashibing.bean;
import java.util.Date;
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private Date hiredate;
private Double sal;
private Double common;
private Integer deptno;
public Emp() {}
public Emp(Integer empno, String ename, String job, Integer mgr, Date hiredate, Double sal, Double common, Integer deptno) {
this.empno = empno;
this.ename = ename;
this.job = job;
this.mgr = mgr;
this.hiredate = hiredate;
this.sal = sal;
this.common = common;
this.deptno = deptno;
}
public Integer getEmpno() {return empno;}
public void setEmpno(Integer empno) {this.empno = empno;}
public String getEname() {return ename;}
public void setEname(String ename) {this.ename = ename;}
public String getJob() {return job;}
public void setJob(String job) {this.job = job;}
public Integer getMgr() {return mgr;}
public void setMgr(Integer mgr) {this.mgr = mgr;}
public Date getHiredate() {return hiredate;}
public void setHiredate(Date hiredate) {this.hiredate = hiredate;}
public Double getSal() {return sal;}
public void setSal(Double sal) {this.sal = sal;}
public Double getCommon() {return common;}
public void setCommon(Double common) {this.common = common;}
public Integer getDeptno() {return deptno;}
public void setDeptno(Integer deptno) {this.deptno = deptno;}
@Override
public String toString() {
return "Emp{" +
"empno=" + empno +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", mgr=" + mgr +
", hiredate=" + hiredate +
", sal=" + sal +
", common=" + common +
", deptno=" + deptno +
'}';
}
}
5、创立对应的 dao 类
EmpDao.java
package com.mashibing.dao;
import com.mashibing.bean.Emp;
public interface EmpDao {public Emp findEmpByEmpno(Integer empno);
}
6、编写配置文件
log4j.properties
# 全局日志配置
log4j.rootLogger=info, stdout
# MyBatis 日志配置
log4j.logger.com.mashibing=TRACE
# 控制台输入
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
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.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/demo?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 引入每一个接口对应点 xml 文件 -->
<mappers>
<mapper resource="EmpDao.xml"/>
</mappers>
</configuration>
EmpDao.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">
<!--namespace: 编写接口的全类名,就是通知要实现该配置文件是哪个接口的具体实现 -->
<mapper namespace="com.mashibing.dao.EmpDao">
<!--
select: 示意这个操作是一个查问操作
id 示意的是要匹配的办法的名称
resultType: 示意返回值的类型,查问操作必须要蕴含返回值的类型
#{属性名}:示意要传递的参数的名称
-->
<select id="findEmpByEmpno" resultType="com.mashibing.bean.Emp">
select * from emp where empno = #{empno}
</select>
</mapper>
7、编写测试类
MyTest.java
package com.mashibing.test;
import com.mashibing.bean.Emp;
import com.mashibing.dao.EmpDao;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyTest {
@Test
public void test01() {
// 依据全局配置文件创立出 SqlSessionFactory
// SqlSessionFactory: 负责创立 SqlSession 对象的工厂
// SqlSession: 示意跟数据库倡议的一次会话
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取数据库的会话
SqlSession sqlSession = sqlSessionFactory.openSession();
Emp empByEmpno = null;
try {
// 获取要调用的接口类
EmpDao mapper = sqlSession.getMapper(EmpDao.class);
// 调用办法开始执行
empByEmpno = mapper.findEmpByEmpno(7369);
} catch (Exception e) {e.printStackTrace();
} finally {sqlSession.close();
}
System.out.println(empByEmpno);
}
}
4、增删改查的基本操作
EmpDao.java
package com.mashibing.dao;
import com.mashibing.bean.Emp;
public interface EmpDao {public Emp findEmpByEmpno(Integer empno);
public int updateEmp(Emp emp);
public int deleteEmp(Integer empno);
public int insertEmp(Emp emp);
}
EmpDao.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">
<!--namespace: 编写接口的全类名,就是通知要实现该配置文件是哪个接口的具体实现 -->
<mapper namespace="com.mashibing.dao.EmpDao">
<!--
select: 示意这个操作是一个查问操作
id 示意的是要匹配的办法的名称
resultType: 示意返回值的类型,查问操作必须要蕴含返回值的类型
#{属性名}:示意要传递的参数的名称
-->
<select id="findEmpByEmpno" resultType="com.mashibing.bean.Emp">
select * from emp where empno = #{empno}
</select>
<!-- 增删改查操作不须要返回值,增删改返回的是影响的行数,mybatis 会主动做判断 -->
<insert id="insertEmp">
insert into emp(empno,ename) values(#{empno},#{ename})
</insert>
<update id="updateEmp">
update emp set ename=#{ename} where empno = #{empno}
</update>
<delete id="deleteEmp">
delete from emp where empno = #{empno}
</delete>
</mapper>
MyTest.java
package com.mashibing.test;
import com.mashibing.bean.Emp;
import com.mashibing.dao.EmpDao;
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 org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyTest {
SqlSessionFactory sqlSessionFactory = null;
@Before
public void init(){
// 依据全局配置文件创立出 SqlSessionFactory
// SqlSessionFactory: 负责创立 SqlSession 对象的工厂
// SqlSession: 示意跟数据库倡议的一次会话
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {e.printStackTrace();
}
}
@Test
public void test01() {
// 获取数据库的会话
SqlSession sqlSession = sqlSessionFactory.openSession();
Emp empByEmpno = null;
try {
// 获取要调用的接口类
EmpDao mapper = sqlSession.getMapper(EmpDao.class);
// 调用办法开始执行
empByEmpno = mapper.findEmpByEmpno(7369);
} catch (Exception e) {e.printStackTrace();
} finally {sqlSession.close();
}
System.out.println(empByEmpno);
}
@Test
public void test02(){SqlSession sqlSession = sqlSessionFactory.openSession();
EmpDao mapper = sqlSession.getMapper(EmpDao.class);
int zhangsan = mapper.insertEmp(new Emp(1111, "zhangsan"));
System.out.println(zhangsan);
sqlSession.commit();
sqlSession.close();}
@Test
public void test03(){SqlSession sqlSession = sqlSessionFactory.openSession();
EmpDao mapper = sqlSession.getMapper(EmpDao.class);
int zhangsan = mapper.updateEmp(new Emp(1111, "lisi"));
System.out.println(zhangsan);
sqlSession.commit();
sqlSession.close();}
@Test
public void test04(){SqlSession sqlSession = sqlSessionFactory.openSession();
EmpDao mapper = sqlSession.getMapper(EmpDao.class);
int zhangsan = mapper.deleteEmp(1111);
System.out.println(zhangsan);
sqlSession.commit();
sqlSession.close();}
}
5、配置文件详解
在 mybatis 的我的项目中,相干的配置在 mybatis-config.xml,这个配置文件是 mybatis 的全局配置文件,用来进行相干的全局配置,在任何操作下都失效的配置。
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>
<!-- 引入内部配置文件,相似于 Spring 中的 property-placeholder
resource: 从类门路引入
url: 从磁盘门路或者网络门路引入
-->
<properties resource="db.properties"></properties>
<!-- 用来管制 mybatis 运行时的行为,是 mybatis 中的重要配置 -->
<settings>
<!-- 设置列名映射的时候是否是驼峰标识 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--typeAliases 示意为咱们援用的实体类起别名,默认状况下咱们须要写类的齐全限定名
如果在此处做了配置,那么能够间接写类的名称, 在 type 中配置上类的齐全限定名,在应用的时候能够疏忽大小写
还能够通过 alias 属性来示意类的别名
-->
<typeAliases>
<!-- <typeAlias type="com.mashibing.bean.Emp" alias="Emp"></typeAlias>-->
<!-- 如果须要援用多个类,那么给每一个类起别名必定会很麻烦,因而能够指定对应的包名,那么默认用的是类名 -->
<package name="com.mashibing.bean"/>
</typeAliases>
<!--
在理论的开发过程中,咱们可能分为开发环境,生产环境,测试环境等等,每个环境的配置能够是不一样的
environment 就用来示意不同环境的细节配置,每一个环境中都须要一个事务管理器以及数据源的配置
咱们在后续的我的项目开发中简直都是应用 spring 中配置的数据源和事务管理器来配置,此处不须要钻研
-->
<!--default: 用来抉择须要的环境 -->
<environments default="development">
<!--id: 示意不同环境的名称 -->
<environment id="development">
<transactionManager type="JDBC"/>
<!-- 配置数据库连贯 -->
<dataSource type="POOLED">
<!-- 应用 ${} 来引入内部变量 -->
<property name="driver" value="${driverClassname}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--
在不同的数据库中,可能 sql 语句的写法是不一样的,为了加强移植性,能够提供不同数据库的操作实现
在编写不同的 sql 语句的时候,能够指定 databaseId 属性来标识以后 sql 语句能够运行在哪个数据库中
-->
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="SQL Server" value="sqlserver"/>
<property name="Oracle" value="orcl"/>
</databaseIdProvider>
<!-- 将 sql 的映射文件实用 mappers 进行映射 -->
<mappers>
<!--
指定具体的不同的配置文件
class: 间接引入接口的全类名,能够将 xml 文件放在 dao 的同级目录下,并且设置雷同的文件名称,同时能够应用注解的形式来进行相干的配置
url: 能够从磁盘或者网络门路查找 sql 映射文件
resource: 在类门路下寻找 sql 映射文件
-->
<!-- <mapper resource="EmpDao.xml"/>
<mapper resource="UserDao.xml"/>
<mapper class="com.mashibing.dao.EmpDaoAnnotation"></mapper>-->
<!--
当蕴含多个配置文件或者配置类的时候,能够应用批量注册的性能,也就是引入对应的包,而不是具体的配置文件或者类
然而须要留神的是,1、如果应用的配置文件的模式,必须要将配置文件跟 dao 类放在一起,这样能力找到对应的配置文件.
如果是 maven 的我的项目的话,还须要增加以下配置,起因是 maven 在编译的文件的时候只会编译 java 文件
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
2、将配置文件在 resources 资源门路下创立跟 dao 雷同的包名
-->
<package name="com.mashibing.dao"/>
</mappers>
</configuration>
EmpDaoAnnotation.java
package com.mashibing.dao;
import com.mashibing.bean.Emp;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
public interface EmpDaoAnnotation {@Select("select * from emp where empno = #{empno}")
public Emp findEmpByEmpno(Integer empno);
@Update("update emp set ename=#{ename} where empno = #{empno}")
public int updateEmp(Emp emp);
@Delete("delete from emp where empno = #{empno}")
public int deleteEmp(Integer empno);
@Insert("insert into emp(empno,ename) values(#{empno},#{ename})")
public int insertEmp(Emp emp);
}