1,mybatis;和数据库进行交互;持久化层框架(sql映射框架);
1),从原始的JDBC----dbutils(QueryRunner)---JdbcTemplate---xxx;(纯手工)
称为工具;
* 工具:一些功能的简单封装
* 框架:某些领域的整体解决方案;缓存,考虑异常处理问题,考虑部分字段映射问题。不用原生jdbc
缺点: 1)麻烦。
2)sql是硬编码;耦合(数据库层和java编码层)
2),hibernate (orm框架)object relation mapping 对象关系映射。(全自动)
比如创建个bean 叫 Employee
@Table("t_employee")
class Employee{
private Integer empId;
private String empName;
}
然后去数据库建一个表t_employee,一 一对应字段。实现自动化操作,甚至不需要写sql语句。
缺点:1,没办法自己编写sql,定制sql。
2,hql。
3,全映射框架;做部分字段映射很难。
mybatis
1,mybatis将重要的步骤抽取出来可以人工定制,其他步骤自动化;
2,重要步骤都是写在配置文件中(好维护);
3,完全解决数据库的优化问题。
4,mybatis底层就是对原生jdbc的一个简单封装;
5,既将java编码与sql抽取了出来,还不会失去自动化功能;半自动的持久层框架。
1)环境搭建
1),创建一个java工程;
2),创建测试库,测试表,以及封装数据的Javabean,和操作数据库的dao接口
创建表:自己用工具创建
创建javabean:Employee ( 封装表的数据 )。
创建一个dao接口,用来操作数据库。
3),开始使用mybatis
1)导包
2)写配置(可以去官方文档,入门级,看如何配置xml文件)
1,第一个配置文件;(称为mybatis的全局配置文件,指导mybatis如何正确运行,比如连接向哪个数据库)
2,第二个配置文件;(编写每一个方法都如何向数据库发送sql语句,如何执行。。。相当于接口实现)
1,将mapper的namespace属性改为接口全类名。
2,配置细节
3,写dao接口的实现文件,mybatis默认是不知道的,需要在全局配置文件中注册;
<!--引入我们自己编写的每一个接口的实现文件-->
<mappers>
<mapper resource="EmployeeDao.xml"/>
</mappers>
3)测试
1,根据全局配置文件先创建一个。
String resource = "conf/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory Factory = new SqlSessionFactoryBuilder().build(inputStream);
2,SqlSessionFactory 中获取 SqlSession 对象操作数据库即可。
//2,获取和数据库的一次会话;getConnection(); SqlSession openSession = Factory.openSession(); //3,使用SqlSession 操作数据库,获取到dao接口的实现。 EmployeeDao mapper = openSession.getMapper(EmployeeDao.class); Employee empById = mapper.getEmpById(1); System.out.println(empById);
--------------------------下面是一套crud的具体代码------------------------
配置文件 和 控制层 的写法都可以在官方文档入门里找到。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.atguigu.bean; /** * Created by Zhuxiang on 2020/6/7. */ public class Employee { private Integer id; private String empName; private String email; private Integer gender; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } public Employee(Integer id, String empName, String email, Integer gender) { this.id = id; this.empName = empName; this.email = email; this.gender = gender; } public Employee() { } public Employee(String empName, String email, Integer gender) { this.empName = empName; this.email = email; this.gender = gender; } @Override public String toString() { return "Employee{" + "id=" + id + ", empName=" + empName + ", email=" + email + ", gender=" + gender + '}'; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.atguigu.dao; import com.atguigu.bean.Employee; /** * Created by Zhuxiang on 2020/6/7. */ public interface EmployeeDao { public Employee getEmpById(Integer i); public int addEmp(Employee emp); public boolean deleteEmp(Integer i); public int updateEmp(Employee emp); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.atguigu.test; import com.atguigu.bean.Employee; import com.atguigu.dao.EmployeeDao; 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.InputStream; /** * Created by Zhuxiang on 2020/6/7. */ public class MyBatisTest { @Test public void test() throws Exception{ //看文档,入门,复制代码。 //1.根据全局配置文件创建出一个SQLSessionFactory //SQLSessionFactory,是SQLSession工厂,复制创建SQLSession对象; //SQLSession:sql会话(代表与数据库的一次会话); String resource = "conf/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory Factory = new SqlSessionFactoryBuilder().build(inputStream); //2,获取和数据库的一次会话;getConnection(); SqlSession openSession = Factory.openSession(); //3,使用SqlSession 操作数据库,获取到dao接口的实现(映射器)。 EmployeeDao mapper = openSession.getMapper(EmployeeDao.class); Employee empById = mapper.getEmpById(1); System.out.println(empById); } //---------------增删改查-------------------- SqlSessionFactory Factory; //junit的before @Before public void initSqlSessionFactory() throws Exception{ String resource = "conf/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); Factory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void test2 ()throws Exception{ SqlSession openSession = Factory.openSession(); EmployeeDao mapper = openSession.getMapper(EmployeeDao.class); try { Employee empById = mapper.getEmpById(1); System.out.println(empById); } finally { openSession.close(); } } @Test public void test3add (){ //方法二:自动提交,参数给个true SqlSession openSession = Factory.openSession(true); EmployeeDao mapper = openSession.getMapper(EmployeeDao.class); try { Employee zx = new Employee("zx", "@qq.123", 0); int i = mapper.addEmp(zx); System.out.println(i); } finally { //方法一:手动提交 //openSession.commit(); openSession.close(); } } @Test public void test3del (){ SqlSession openSession = Factory.openSession(true); EmployeeDao mapper = openSession.getMapper(EmployeeDao.class); try { boolean i = mapper.deleteEmp(2); System.out.println(i); } finally { openSession.close(); } } @Test public void test3update (){ SqlSession openSession = Factory.openSession(true); EmployeeDao mapper = openSession.getMapper(EmployeeDao.class); try { Employee emp = new Employee(); emp.setEmpName("sss"); emp.setId(1); int i = mapper.updateEmp(emp); System.out.println(i); } finally { openSession.close(); } } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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 名称空间:写接口的全类名,相当于告诉 mybatis 这个配置文件是实现哪个接口的--> <mapper namespace="com.atguigu.dao.EmployeeDao"> <!--select 用来定义一个查询操作 id 方法名,相当于这个配置是对于某个方法的实现 resultType 指定方法运行后的返回值类型(查询操作必须指定的) #{属性名} 代表取出传递过来的某个参数的值 --> <select id="getEmpById" resultType="com.atguigu.bean.Employee"> <!--sql语句不要写分号--> select * from t_employee where id=#{id} </select> <!--增删改不用写返回值类型,增删改是返回影响多少行--> <!--mybatis自动判断,如果是数字(int,long),如果是boolean(影响0行自动封装false,否则true)--> <update id="updateEmp"> update t_employee set empname=#{empName} where id=#{id} </update> <delete id="deleteEmp"> delete from t_employee where id=#{id} </delete> <insert id="addEmp"> insert into t_employee(empName,email,gender) values (#{empName},#{email},#{gender}) </insert> </mapper>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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/spring1"/> <property name="username" value="root"/> <property name="password" value=""/> </dataSource> </environment> </environments> <!--引入我们自己编写的每一个接口的实现文件--> <mappers> <mapper resource="conf/EmployeeDao.xml"/> </mappers> </configuration>
-------------------------------官方文档里看完入门,该看配置了------------------------------------
1,全局配置文件:mybatis-config.xml;指导mybatis正确运行的一些全局设置;
2,sql映射文件:EmployeeDao.xml;相当于是对dao接口的一个实现描述。
-
configuration 配置
-
properties 属性
-
settings 设置
-
typeAliases 类型命名(起别名,不太用)
-
typeHandlers 类型处理器(不用)
-
objectFactory 对象工厂(不用)
-
plugins 插件(用的不多)
-
environments 环境databaseIdProvider 数据库厂商标识( 不用 )
- environment 环境变量
- transactionManager 事务管理器
- dataSource 数据源
- environment 环境变量
-
mappers 映射器
-
去官方文档看,有例子。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <!--引入外部配置文件--> <!--1.properties resource:从类路径下开始引用 url:引用磁盘路径或者网络路径的资源 --> <properties resource="conf/dbconfig.properties"></properties> <!--2.settings 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。 mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camel case)映射, 即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 说得简单点就是,根据这个规则,数据库列名里 _ 后面的第一个字母,在javabean里是大写,然后可以匹配。 如: javabean里属性名叫:loginAccount 数据库列名为:login_account 可以匹配--> <!--name:配置项的key value:配置项的值 --> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <!--3.(不推荐用!!!!知道就行)类型别名,为常用的类型(如javabean)起别名--> <typeAliases> <!--typeAlias:就是为一个javabean起别名,别名默认就是类名(不区分大小写),配置文件中就可以用别名了 alias:指定一个别名。--> <!-- <typeAlias type="com.atguigu.bean.Employee" alias="Employee"></typeAlias>--> <!--批量起别名,name="" 指定包名,默认别名就是类名.到javabean里用注解自定义别名--> <!-- <package name="com.atguigu.bean"></package>--> </typeAliases> <!--4.typeHandlers。(不用!!!)无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时, 还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。--> <!--5,插件是mybatis中的一个强大功能?(不用)--> <!--environments 配置环境们 environment:配置一个具体的环境,都需要一个事务管理器和一个数据源。 transactionManager: 后来数据源和事务管理都是spring来做。 --> <!--default="" 默认使用哪个环境。--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!--配置连接池--> <!--用${}取值--> <dataSource type="POOLED"> <property name="driver" value="${driverclass}"/> <property name="url" value="${jdbcurl}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!--6.(不用!)mybatis用来考虑数据库移植性的。比如从mysql移植到Oracle数据库--> <databaseIdProvider type="DB_VENDOR"> <!--name="" ,数据库厂商标识 value 给这个标识起一个好用的名字--> <property name="MySQL" value="mysql"/> <property name="SQL Server" value="sqlserver"/> <property name="Oracle" value="oracle"/> </databaseIdProvider> <!--引入我们自己编写的每一个接口的实现文件--> <mappers> <!--7.注册映射文件 7.1 resource:从类路径下开始引用(推荐) url:引用磁盘路径或者网络路径的资源 class:直接引用接口的全类名 (需要将xml文件放在dao接口同目录下,而且文件名和接口名一致) --> <mapper resource="conf/EmployeeDao.xml"/> <!--7.2 批量注册 name="", dao所在的包名 (需要将xml文件放在dao接口同目录下,而且文件名和接口名一致)--> <!-- <package name="com.atguigu.dao"/>--> </mappers> </configuration>
objectFactory 对象工厂 配置 dao.xml 文件
<!--数据库切换,如果能精确匹配就精确,不能就用模糊的-->
<!-- <select id="getEmpById" resultType="com.atguigu.bean.Employee" databaseId="oracle">-->
<!-- <!–sql语句不要写分号–>-->
<!-- select * from t_employee where id=#{id}-->
<!-- </select>-->
------------------------全局配置文件介绍完毕,现在介绍sql映射文件--------------------------------
-----------------关于动态sql我们可以直接去mybatis官网上看,内容是一样的。--------------------
------------------------------------------缓存----------------------------------------------
暂时的储存一些数据,加快系统的查询速度。
cpu:会把数据先放在内存条里,这就算缓存。
cpu还有自己的缓存区,一级缓存,二级缓存;
数据库交互:
比如去数据库查一个类;mybatis缓存机制;存在map里;能保存查询出的一些数据。
一级缓存:线程级别的缓存;本地缓存;sqlsession级别的缓存。(sqlsession就是开启一次连接)
二级缓存:全局范围的缓存;除过当前线程,或者说,sqlsession能用外其他也可以使用。
一级缓存:mybatis:
默认存在。证明:连续写查询同一个类2次。1,日志中只打印一次sql语句。2,(第一次查询结果==第二次查询结果)结果为true,证明内存一致。
1)只要之前查询过的数据,mybatis就会保存在一个缓存中(map);下次获取直接从缓存中拿。
一级缓存失效的情况:
1)因为是sqlsession级别的缓存,所以不同的sqlsession,使用不同的一级缓存。
只有在同一个sqlsession期间查询到的数据会保存在这个sqlsession的缓存中。
2)同一个sqlsession期间,同一个方法,但是不同参数,会发新的sql。
3)同一个sqlsession期间,执行上任何一次增删改操作,增删改操作会把之前的缓存清空。
4)手动清空缓存。
二级缓存:
1,不会出现一级缓存和二级缓存中有同一个数据。
二级缓存中:一级缓存关闭了就有了;
一级缓存中:二级缓存中没有此数据,就会看一级缓存,一级缓存也没有,就去查数据库;
查询后的结果放在一级缓存里。
2,优先查看顺序,口诀:二——一——库。
------------------------整合第三方缓存------------------------
因为mybatis是专业做数据库的,他的缓存做的不太行,所以他给了接口和实现。用接口来整合第三方包,可以用专业的内存数据库。
比如:整合ehcache;ehcache是非常专业的java进程内的缓存框架。
3,(补充)在mapper.xml中配置使用cache标签。
(补充)<cache-ref namespace="和别的dao,共用一块缓存,填dao路径 "/>
建议:ehcache.xml要放在类路径的根目录下。