在mybatis初次学习Mybatis的时候,遇到了不少问题,虽然阿里云的视频有教学,可是视频教学所使用的软件和我本身使用的软件不用,我本身用的数据库是oracle数据库,开发环境是idea。并且视频中只是将mybatis这一部分抽出来说,实际上还须要一些知识储备,我自己是了解了oralce基本的操做后,再开始学习Mybatis的,过程可能会走不少弯路,和遇到不少不理解或者理解错误的地方,如今暂时只能囫囵吞枣,等有必定了解后,再回头看看,总结和更改个人一些认知。java
Mybatis是什么?mysql
mybatis是基于java持久层的框架,持久层就是把业务数据存储到硬盘,在断电或者重启系统后,仍然能够读取这些数据。就好像玩游戏须要保存进度同样,否则每次都须要重头开始玩。java互联网能够经过mybatis框架访问数据库。程序员
没有Mybatis以前怎么访问数据库?
在早期,若是须要访问oracle数据库,须要专门写一个程序,若是访问mysql,又须要专门写一个程序,后来就有了jdbc(Java DataBase Connectivity,java数据库链接),jdbc是一种用来执行sql语句的java api,能够为多种数据库提供统一的访问。简单来讲,它能够与数据库创建链接,发生操做数据库的语句,处理结果。可是jdbc的工做量也是很大的,并且很很差用,因此出现了ORM(Object relational Mapping,对象关系映射 ),咱们把POJO对象和数据库表相互映射的框架称为ORM,mybatis和hibernate都是ORM框架,并且由于mybatis对jdbc的封装很好,并且很灵活,因此几乎能够彻底取代jdbc。sql
Mybatis的优势
mybatis有三个优势:数据库
除了mybatis,还有其余框架,好比Hibernate,hibernate与mybatis一样是java持久层的框架,均可以经过注解或者xml提供映射规则。可是hibernate不须要编写SQL就能够经过映射关系去操做数据库,这样程序员不须要精通SQL,只须要操做POJO(Plain Ordinary Java Object,简单的java对象)就能够操做对应的数据库的表了,可是这也是缺点,当多表关联超过3个,hibernate的性能就会丢失,而mybatis能够自定义SQL,映射关系,因此,他比hibernate更加灵活。可是mybatis也有缺点,由于须要编写SQL和映射规则,因此工做量比hibernate多。因此若是系统对性能要求不高时,能够实用hibernate,若是对性能要求高可使用mybatis。apache
Mybatis的核心组件
首先先了解mybatis的核心组件有哪些,而后再去了解这些组件的做用和实现原理。mybatis的核心组件分为4个部分:编程
Mybatis的配置
开始配置以前,须要准备Mybatis环境,我使用的mybatis版本是3.5.0.而后导入相关jar包。
既然用的mybatis,固然须要mybatis的核心jar包,和lib文件下的jar包,以下图:
由于链接的是oracle数据库,因此还须要oracle的jar包,个人地址是:H:\app\zheng\product\12.2.0\dbhome_1\jdbc\lib
jar包都导入项目后,才能够正式开始。c#
首先获取一个SqlSessionFactory,,Mybatis提供了SqlSessionFactoryBuilder来生成SqlSessionfactory,能够经过XML配置文件或者java代码去生成SqlSessionFactory。这里建议用XML来生成SqlSessionFactory,由于代码的方式会在须要修改的时候比较麻烦。
在mybaits中,由于这是基础配置文件(XML有两类,一类是基础配置文件,主要是配置上下文参数和运行环境,下面的XML就是基础配置文件,另外一类就是映射文件,后面会用到),因此取名mybaits.cfg.xml。mybatis说明文档中XML代码以下:
大部分地方复制过来就能够了,只须要改一下数据源的配置,driver填OracleDriver这个驱动器类的全限定名。url的写法有多种,username,password就是链接数据库用的用户,和密码,这里就不详细说明了。 <mappers>元素表明引入哪些映射器,咱们后面会用新建一个叫product.mapper.xml的映射文件。因此这里写上这个映射文件。稍微改一下XML文件,代码以下:api
<?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="oracle.jdbc.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@//DESKTOP-997L86A:1521/orcl"/> <property name="username" value="c##scott"/> <property name="password" value="tiger"/> </dataSource> </environment> </environments> <!--映射文件--> <mappers> <mapper resource="product.mapper.xml"/> </mappers> </configuration>
而后是去生成SqlSessionFactory了。说明文档中写了能够用下面的代码去生成SqlSessionFactory:
固然这里也须要改一下,把resource换成本身刚才写的XML文件就好了。而后我是把这个方法写在一个getSqlSessionFactory静态方法里面的,这样能够方法生成SqlSessionFactory。新建MyBatisUtil类,代码以下:session
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 MyBatisUtil { public static SqlSessionFactory getSqlSessionFactory() throws IOException { String resource = "mybatis.cfg.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); return sqlSessionFactory; } }
而后是建立SqlSession,有了SqlSessionFactory后,建立SqlSession就很简单了,一行代码就能够,咱们一样把它写在一个静态方法里面,和上面的getSqlSessionFactory()方法放在一块儿。代码以下:
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 MyBatisUtil { public static SqlSessionFactory getSqlSessionFactory() throws IOException { String resource = "mybatis.cfg.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); return sqlSessionFactory; } public static SqlSession getSqlSession() throws IOException { SqlSessionFactory sqlSessionFactory=getSqlSessionFactory(); return sqlSessionFactory.openSession(); } }
以前说过,mybatis中XML有两类,一个是以前写的基础配置文件,还有一个就是接下来的映射器文件。映射文件能够用XML或者注解实现,这里咱们一样推荐使用XML实现,由于若是同时使用XML和注解定义的话,XML会覆盖掉注解方式。并且当Sql语句比较复杂时,使用注解方式也会下降可读性,灵活性也不如XML。
映射器的主要就是将SQL查询到的结果映射为一个POJO,或者将POJO的数据插入数据库,因此须要先定义一个POJO。
这是用来测试的Testtable表格,只有一个id和名字。
对应的POJO:
public class Testtable { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
用XML定义映射器分为两个部分:接口和XML。我在看视频的时候,老师一开始是没有讲接口的,因此这里就先不使用接口来建立映射器。那么在有了POJO后,只须要配置一下XML文件就能够实现映射器了。product.mapper.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="ProductMapper"> <select id="selectTesttable_id" parameterType="int" resultType="Testtable"> select * from Testtable where id = #{id} </select> <select id="selectTesttable_name" parameterType="String" resultType="Testtable"> select * from Testtable where name = #{id} </select> </mapper>
<mapper namespace="ProductMapper">所使用的是接口的全限定名,由于没有接口,因此这里随便写。
<select>元素就是代表查询语句了,id标识哪一条SQL。
parameterType是传递进去的参数类型,好像不写也能够。
resultType是返回类型。
#{id}表示传递进去的参数。
我这里写了两条SQL语句,分别是查询条件为id的selectTesttable_id,和查询条件为name的selectTesttable_name。Mybatis提供自动映射,能够把SQl返回的列名和POJO对应起来,
使用SqlSession发送sql
有了映射器后,就能够经过SqlSession发送SQL了。代码以下:
import org.apache.ibatis.session.SqlSession; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { SqlSession sqlSession=MyBatisUtil.getSqlSession();//获取SqlSession Testtable testtable1=sqlSession.selectOne("ProductMapper.selectTesttable_id",003);//使用ProductMapper配置文件下的selectTesttable_id语句,查询条件为where id = 003 Testtable testtable2=sqlSession.selectOne("ProductMapper.selectTesttable_name","菜刀");//使用ProductMapper配置文件下的selectTesttable_name,查询条件为where name = ‘菜刀’ System.out.println("id="+testtable1.getId()+"名字="+testtable1.getName()); System.out.println("id="+testtable2.getId()+"名字="+testtable2.getName()); sqlSession.close();//关闭资源。 } }
查询结果以下
selectOne方法有两个参数,一个String对象,和一个Object对象,String是由命名空间加SQL id组成的。由此来肯定惟一一条SQL语句,Object由以前的<select>元素中的parameterType肯定的。 selectOne方法会返回一个Testtable类型的对象,书中用了转换:
Testtable testtable1=(Testtable)sqlSession.selectOne("ProductMapper.selectTesttable_id",003);
可是实际上不用转换,能够直接使用。
注意必定要sqlSession.close();关闭资源,若是不关闭,数据库的链接资源很快就会耗费逛,整个系统就会陷入瘫痪。这就是直接用SqlSession发送SQL语句,接下来使用SqlSession去获取Mapper接口,经过Mapper接口发送语句。
使用Mapper接口发送sql
既然使用Mapper接口发送语句,那么就须要先定义一个映射器接口。代码以下
public interface TesttableMapper { public Testtable selectTesttable_id(int id); }
这个方法的名字就是SELECT语句id的名字,参数就是#{id}。
修改product.mapper.xml文件里的<mapper namespace="ProductMapper">,改为新建的接口名。<mapper namespace="TesttableMapper">
测试代码以下:
TesttableMapper testtableMapper=sqlSession.getMapper(TesttableMapper.class); Testtable testtable3=testtableMapper.selectTesttable_id(002); System.out.println("id="+testtable3.getId()+" 名字="+testtable3.getName()); sqlSession.close();
注意TesttableMapper这个接口是没有实现类的,可是mybatis运用了动态代理技术,为这个接口生成了一个代理对象。使得接口也能运行起来。
两种发送sql的方式的区别 使用Mapper发送SQl能够提升可读性,更能体现业务逻辑testtableMapper.selectTesttable_id(002)的写法也更符合面向对象的语言。并且使用Mapper,IDE会提示报错。Sqlsession去发生SQL语言只会在运行期间报错。如今基本上都是使用Mapper接口编程。