1.Mybatis介绍:
mybatis是一款用于持久层的、轻量级的半自动化ORM框架,封装了所有jdbc操作以及设置查询参数和获取结果集的操作,支持自定义sql、存储过程和高级映射。
这句话大体是可以总结mybatis的,对于初学者来说,当看到这句话时是否会有一些问题在你脑海中产生呢?是否有如下疑问:
持久层是什么?轻量级什么概念?ORM什么意思?jdbc是什么?高级映射又是哪些映射?
接下来,一个个的解决这些问题。
持久层是什么意思呢,可以把层字去掉,持久,也就是”保持长久“的意思,他针对的是系统中数据存在的时限,而非其他。有一个基本问题大家应该知道,在内存中的数据是不持久的,如果计算机崩溃或者其他原因导致关机,数据就会丢失,但是磁盘上的数据是持久的,因此,用在持久层也就是这个框架是用来将内存中的数据写入到磁盘中的,再具体一点,就是写到数据库中。所以,总结一下,框架用于持久层,就是说这个框架是和数据库进行交互的,用于数据库中数据操作的框架。
轻量级框架的概念可以简单的理解为所用框架开发的程序启动时占用的资源少、对业务代码的侵入性不强、比较容易配置、使用和部署简单、独立部署即可使用无需依赖另外的框架,这种就是轻量级框架,相反的就是重量级。在互联网飞速发展和产品迭代更新速度如此之快的今天,轻量级的框架更容易被接受,这也是spring胜出,EJB退出的原因。
ORM,Object Relational Mapping, 直接翻译就是对象关系映射,我也没有更好的解释,看一下百科上是这样介绍的”用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生”。这里简单的可以这样理解,java中的数据类和数据库之间的类型系统不同,因此在使用java处理数据库时,需要进行对应的类型转化,而mybatis可以做这个事,可以将java中的类型一一映射到数据库的字段类型上,因此可以将其看作是一个ORM框架。那为什么又是半自动ORM框架呢?使用mybatis,需要手动配置pojo、sql和映射关系,用户可以自定义sql,这些sql是针对于处理数据库的,但是这些sql需要接受一些查询java类型的参数,或者是返回结果集封装到java类中,这些是需要配置的,因此mybatis是一个半自动ORM框架。说到底还是因为需要写sql,才能将数据库中的数据映射到java类中,而不是直接根据java类获取到对应数据库中数据。这里多说一下,hibernate是一个全自动的ORM框架,因为只需要提供pojo和映射关系即可,后期可以直接根据pojo获取到数据。
最后就是高级映射是什么,这里可以类比数据表之间的映射关系,也就是一对一、一对多、多对多。
2.搭建mybatis框架环
首先先创建一个项目,根据上图选好自己文件的安装路径,在Arecehtype点击下拉框选择我们最后一个单词为webapp然后点击确定即可
创建好后配置我们的pom.xml文件(导入依赖)
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>mybatis01</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>mybatis01 Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>mybatis01</finalName> <resources> <!--解决mybatis-generator-maven-plugin运行时没有将XxxMapper.xml文件放入target文件夹的问题--> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <!--解决mybatis-generator-maven-plugin运行时没有将jdbc.properites文件放入target文件夹的问题--> <resource> <directory>src/main/resources</directory> <includes> <include>jdbc.properties</include> <include>*.xml</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <dependencies> <!--使用Mybatis-generator插件不能使用太高版本的mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.44</version> </dependency> </dependencies> <configuration> <overwrite>true</overwrite> </configuration> </plugin> </plugins> </build> </project>
创建我们连接文件例如:我这里要连接的数据库为mysql的数据库
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis_ssm?useUnicode=true&characterEncoding=UTF-8 jdbc.username=mybatis_ssm jdbc.password=123456
接着就是修改我们的web.xml文件
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"></web-app>
接下来创建我们的java包即可;
然后安装插件:
Free mybatis plugin 注意(如果没有就安装mybatisx)
Mybatis generator
mybatis tools
maven helper
让后书写插件配置文件
mybatis.cfg.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="jdbc.properties"/> <settings> <setting name="logImpl" value="LOG4J2"/> </settings> <!-- 别名 --> <typeAliases> <!--<typeAlias type="com.javaxl.model.Book" alias="Book"/>--> </typeAliases> <!-- 配置mybatis运行环境 --> <environments default="development"> <environment id="development"> <!-- type="JDBC" 代表使用JDBC的提交和回滚来管理事务 --> <transactionManager type="jdbc"/> <!-- mybatis提供了3种数据源类型,分别是:POOLED,UNPOOLED,JNDI --> <!-- POOLED 表示支持JDBC数据源连接池 --> <!-- UNPOOLED 表示不支持数据源连接池 --> <!-- JNDI 表示支持外部数据源连接池 --> <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="com/javaxl/mapper/BookMapper.xml"/>--> <!-- </mappers>--> </configuration>
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <!-- 引入配置文件 --> <properties resource="jdbc.properties"/> <!--指定数据库jdbc驱动jar包的位置--> <classPathEntry location="D:\\tools\\mvn_repository\\mysql\\mysql-connector-java\\5.1.44"/> <!-- 一个数据库一个context --> <context id="infoGuardian"> <!-- 注释 --> <commentGenerator> <property name="suppressAllComments" value="true"/><!-- 是否取消注释 --> <property name="suppressDate" value="true"/> <!-- 是否生成注释代时间戳 --> </commentGenerator> <!-- jdbc连接 --> <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/> <!-- 类型转换 --> <javaTypeResolver> <!-- 是否使用bigDecimal, false可自动转化以下类型(Long, Integer, Short, etc.) --> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- 01 指定javaBean生成的位置 --> <!-- targetPackage:指定生成的model生成所在的包名 --> <!-- targetProject:指定在该项目下所在的路径 --> <javaModelGenerator targetPackage="com.xzs.model" targetProject="src/main/java"> <!-- 是否允许子包,即targetPackage.schemaName.tableName --> <property name="enableSubPackages" value="false"/> <!-- 是否对model添加构造函数 --> <property name="constructorBased" value="true"/> <!-- 是否针对string类型的字段在set的时候进行trim调用 --> <property name="trimStrings" value="false"/> <!-- 建立的Model对象是否 不可改变 即生成的Model对象不会有 setter方法,只有构造方法 --> <property name="immutable" value="false"/> </javaModelGenerator> <!-- 02 指定sql映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.xzs.mapper" targetProject="src/main/java"> <!-- 是否允许子包,即targetPackage.schemaName.tableName --> <property name="enableSubPackages" value="false"/> </sqlMapGenerator> <!-- 03 生成XxxMapper接口 --> <!-- type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象 --> <!-- type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象 --> <!-- type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 --> <javaClientGenerator targetPackage="com.xzs.mapper" targetProject="src/main/java" type="XMLMAPPER"> <!-- 是否在当前路径下新加一层schema,false路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] --> <property name="enableSubPackages" value="false"/> </javaClientGenerator> <!-- 配置表信息 --> <!-- schema即为数据库名 --> <!-- tableName为对应的数据库表 --> <!-- domainObjectName是要生成的实体类 --> <!-- enable*ByExample是否生成 example类 --> <!--<table schema="" tableName="t_book" domainObjectName="Book"--> <!--enableCountByExample="false" enableDeleteByExample="false"--> <!--enableSelectByExample="false" enableUpdateByExample="false">--> <!--<!– 忽略列,不生成bean 字段 –>--> <!--<!– <ignoreColumn column="FRED" /> –>--> <!--<!– 指定列的java数据类型 –>--> <!--<!– <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> –>--> <!--</table>--> <table schema="" tableName="t_mvc_Book" domainObjectName="Book" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> <!-- 忽略列,不生成bean 字段 --> <!-- <ignoreColumn column="FRED" /> --> <!-- 指定列的java数据类型 --> <!-- <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> --> </table> </context> </generatorConfiguration>
根据上述代码提示中修改即可
注意!mybatis不能使用太高mysql帮本
那么搭建mybatis的框架就搭建好了
3.代码生成
在配置好后
双击插件mybatis-generatorg即可
就会根据你generatorConfig.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="com.xzs.mapper.BookMapper" >//对应的模块 <resultMap id="BaseResultMap" type="com.xzs.model.Book" >//对应着接口里SQL语句的方法标签 <constructor > <idArg column="bid" jdbcType="INTEGER" javaType="java.lang.Integer" /> <arg column="bname" jdbcType="VARCHAR" javaType="java.lang.String" /> <arg column="price" jdbcType="REAL" javaType="java.lang.Float" /> </constructor> </resultMap> <sql id="Base_Column_List" > bid, bname, price </sql> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" > select <include refid="Base_Column_List" /> from t_mvc_book where bid = #{bid,jdbcType=INTEGER} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" > delete from t_mvc_book where bid = #{bid,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="com.xzs.model.Book" > insert into t_mvc_book (bid, bname, price ) values (#{bid,jdbcType=INTEGER}, #{bname,jdbcType=VARCHAR}, #{price,jdbcType=REAL} ) </insert> <insert id="insertSelective" parameterType="com.xzs.model.Book" > insert into t_mvc_book <trim prefix="(" suffix=")" suffixOverrides="," > <if test="bid != null" > bid, </if> <if test="bname != null" > bname, </if> <if test="price != null" > price, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides="," > <if test="bid != null" > #{bid,jdbcType=INTEGER}, </if> <if test="bname != null" > #{bname,jdbcType=VARCHAR}, </if> <if test="price != null" > #{price,jdbcType=REAL}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="com.xzs.model.Book" > update t_mvc_book <set > <if test="bname != null" > bname = #{bname,jdbcType=VARCHAR}, </if> <if test="price != null" > price = #{price,jdbcType=REAL}, </if> </set> where bid = #{bid,jdbcType=INTEGER} </update> <update id="updateByPrimaryKey" parameterType="com.xzs.model.Book" > update t_mvc_book set bname = #{bname,jdbcType=VARCHAR}, price = #{price,jdbcType=REAL} where bid = #{bid,jdbcType=INTEGER} </update> </mapper>
那么思考一个问题,如果一个实体类如以上代码所示只有三个属性如图所示
那么是不是代表着我们有多少个指端对应数量的标签,所以为了解决这个问题
实现了代码的复用,也就是
3. 实现增删改查:
BookMapper接口:
package com.xzs.mapper; import com.xzs.model.Book; public interface BookMapper { int deleteByPrimaryKey(Integer bid); int insert(Book record); int insertSelective(Book record); Book selectByPrimaryKey(Integer bid); int updateByPrimaryKeySelective(Book record); int updateByPrimaryKey(Book record); }
BookBizIMpl实现类
package com.xzs.mapper.impl; import com.xzs.mapper.BookMapper; import com.xzs.model.Book; public class BookBizImpl implements BookMapper { private BookMapper bookmapper; @Override public int deleteByPrimaryKey(Integer bid) { return bookmapper.deleteByPrimaryKey(bid); } @Override public int insert(Book record) { return bookmapper.insert(record); } @Override public int insertSelective(Book record) { return bookmapper.insertSelective(record); } @Override public Book selectByPrimaryKey(Integer bid) { return bookmapper.selectByPrimaryKey(bid); } @Override public int updateByPrimaryKeySelective(Book record) { return bookmapper.updateByPrimaryKeySelective(record); } @Override public int updateByPrimaryKey(Book record) { return bookmapper.updateByPrimaryKey(record); } }
编写工厂类
package com.xzs.utils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; /** * @author 小李飞刀 * @site www.javaxl.com * @company xxx公司 * @create 2018-12-10 21:59 */ public class SessionUtil { private static SqlSessionFactory sessionFactory; private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>(); static { sessionFactory = new SqlSessionFactoryBuilder().build(SessionUtil.class.getResourceAsStream("/mybatis.cfg.xml")); //生产sqlsession的 } public static SqlSession openSession() { SqlSession session = threadLocal.get(); if (null == session) { session = sessionFactory.openSession(); threadLocal.set(session); } return session; } public static void main(String[] args) { SqlSession session = openSession(); System.out.println(session.getConnection()); session.close(); // System.out.println(session.getConnection()); } }
测试类
package com.xzs.mapper.demo; import com.xzs.mapper.BookMapper; import com.xzs.mapper.impl.BookBizImpl; import com.xzs.model.Book; import com.xzs.utils.SessionUtil; import org.apache.ibatis.annotations.ResultType; import org.apache.ibatis.session.SqlSession; import org.junit.After; import org.junit.Before; import org.junit.Test; public class demo { private SqlSession sqlSession; private BookMapper bookMapper; @Before public void a(){ System.out.println("测试之前执行"); System.out.println("执行测试方法之前会执行的初始化代码块方法"); //获取一个数据库会话对象,并将其赋值给sqlSession变量 this.sqlSession = SessionUtil.openSession(); //实例化业务逻辑层 BookBizImpl book = new BookBizImpl(); //获取接口实例 BookMapper mapper = this.sqlSession.getMapper(BookMapper.class); book.setBookmapper(mapper); //最后赋值给bookBiz接口,便于对数据库进行增删改查操作 this.bookMapper = book; } @After public void b(){ System.out.println("测试之后执行"); } @Test public void test1(){ System.out.println("测试方法"); Book book = bookMapper.selectByPrimaryKey(100); System.out.println(book); } }
结果: