Mybatis入门

tech2024-02-20  57

一.Mybaits持久层框架

1.概念

mybatis是一个持久层框架,持久层就是将程序运行过程中的数据永久的储存,这一个的一个转换过程。名命 DAO,将数据储存在数据库中

2.回顾

通过oracle的JDBC api对数据库进行访问 JDBC整个都是一个规范,是一组接口,具体的实现驱动由各个数据库厂商完成。 JDBC五大步骤 加载驱动 创建连接 创建执行对象 进行CRUD操作 释放资源【非常的重要】 通过以上的五个步骤就可以对数据库进行访问,访问的时候问题: private DBManager db=new DBManager(); public List<Account> queryAll(){ String sql ="select * from account"; Resultset rs = db.query(sql); while(rs.next()){ //有大量的解析代码 Account account=new Account(); account.setxxx(rs.getXXX("列名")); //如果列很多,那么代码很繁琐 } } 还有一个问题,释放资源(关闭连接)必须要做 private DBManager db=new DBManager(); public List<Account> queryAll(){ try{ String sql ="select * from account"; Resultset rs = db.query(sql); while(rs.next()){ //有大量的解析代码 Account account=new Account(); account.setxxx(rs.getXXX("列名")); //如果列很多,那么代码很繁琐 } }finally{ db.close(); } } 所有的dao代码都必须有一个统一的模板进行编码,try finally 传统的dao模块开发,存在以上 resultset解析繁琐,代码冗余问题。 还存在比如sql没办法查看。复杂的查询sql,sql不好维护。 每次查询都是物理查询,查询id为1的account信息,每一次都需要和数据库进行交互,解析,关闭... connection连接的创建 消耗资源 所有的dao层框架,都是解决以上问题的 在dao层框架,鼎鼎有名 hibernate,mybatis

3.名词辨析

技术、组件、框架、系统

技术:解决某一类问题的方法和手段,jdbc技术,jsp技术 组件:应用程序中可以复用的“零件”(封装的类库),分页组件,数据库访问组件 框架:Framework,是构成一组特定软件可复用设计的一组相互协助工作的类,是一个程序的半 成品。生活中的简历模板,盖房子,钢构结构,活动板房。 系统:实现了完整功能的应用程序,淘宝系统,网上交易系统。

4.JavaWeb阶段回顾

程序主要处理的就是数据,数据通常会被存储在数据库(MySQL、Oracle、NoSQL)或内存中。

Java和数据库的操作:Sun公司提供的JDBC接口规范API,具体的接口实现由各家数据库厂商实现。

传统JDBC如何操作数据库?

加载驱动 Class.forName("com.mysql.jdbc.Driver"); 获取连接 DriverManager.getConnection(url, username, password); 创建执行对象 conn.prepareStatement("sql"); 进行CRUD操作--->解析结果集 ps.setXXX()/ps.executeUpdate()/ps.executeQuery()/while(rs.next()) rs.getXXX("列名") 释放连接 底层抛出异常,高层抓取异常。 (DAO层抛出异常)

从JavaWeb阶段的学习,我们可以发现

DAO模块:

DAO模块中为了要释放连接,普遍都是try-finally代码块;SQL代码与Java代码耦合;SQL的参数设置,preparedStatement.setXxx(),有些繁琐;SQL作为字符串形式写在参数中,可读性差,尤其是当SQL是复杂SQL时,连接查询、子查询等;读取结果集时设置对象参数复杂,如果对象属性(表的字段)有特别多时,逐一setXxx(rs.getXxx())不现实;每次查询都是物理查询,没有缓存的功能

综合所述,参数映射、结果集映射、缓存、多表连接查询等等问题如果实现了,那将不简单是技术,而是框架。

Controller模块:

Servlet读取浏览器、表单参数过程复杂;一个Servlet只能处理一个请求/多个urlPatterns,导致Servlet过多;Servlet支持的视图类型:html、jsp;不支持json;…

二.框架介绍

1.概述

前端: ​js:jquery,vue ​h5:bootstrap Spring: ​Spring贯穿整个应用程序,也就是后台三层中都是使用到了spring,IOC,AOP,萌芽2000年,诞生于2004年 Servlet: ​MVC框架 ​SpringMVC(最优秀的mvc框架),Spring的后续产品2005年 ​Struts(退出舞台了) Struts2(奄奄一息,老系统还要维护) 2000年产物 DAO: ​Mybatis(互联网项目很流行)2010年,早期ibatis,后来google,更名为Mybatis 2013 ​Hibernate(老系统在维护,或者新的系统但不怎么更改更新) SSH-> Spring + Struts2 + Hibernate SSM-> Spring + SpringMVC + Mybatis 前面都是基础,后面才能学习 Spring Boot :简化Spring开发的,SSM做一个查询,需要30分钟,Spring Boot只需要5分钟不到,2014年 Spring Colud:微服务一站式框架,架构

2.ORM框架

ORM(Object Relational Mapper)对象关系映射。 O—>Java对象 R—>数据库表 M—>映射文件 一个Java类对应数据库中的一张表; 一个Java属性对应数据库中的一个字段; 一个Java对象对应数据库中的一个对象 mybatis不完全的orm映射框架保存一条记录,映射配置有一些是不可见的 hibernate是一个完全的orm映射框架保存一条记录-> save(account);映射关系是必须配置的明确

3.Mybatis简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。 MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。 MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

4.快速入门

环境配备

IDEA jdk1.8 和 jdk11 对应mybatis懒加载支持是有区别的 maven3.6.1 (配置中央仓库aliyun)

数据库脚本

CREATE DATABASE mybatis; USE mybatis; CREATE TABLE account ( aid INT PRIMARY KEY AUTO_INCREMENT, aname VARCHAR(20) NOT NULL, apassword VARCHAR(20) NOT NULL, a_nickname VARCHAR(20) NOT NULL ); INSERT INTO account VALUES(1, 'zhangsan', '123456', '张三'); INSERT INTO account VALUES(2, 'lisi', '123456', '李四');

数据库脚本所有的框架开发,遵循以下流程:

1 maven依赖,jar包拿过来

2 编写核心配置文件

3 根据框架的api编码

4 测试

5.新建普通Maven项目,导入依赖

MyBatis最新版本:3.5.5

数据库驱动:5.1.47

Lombok:简化POJO类的开发

Junit:测试Mapper。

在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>org.example</groupId> <artifactId>Mybatis02</artifactId> <version>1.0-SNAPSHOT</version> <!--添加项目依赖--> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <!--数据库驱动--> <!--驱动的版本最好和你的数据库版本保持一致--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <!--alibaba json工具,他和mybatis没关系--> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <!-- 这次我是放在src/main/java目录下,配置build标签。 --> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build> </project>

6.编写配置文件

任何的数据库访问框架,都需要最基础的四项内容,驱动字符串,连接字符串,用户名,数据库密码. 位置放在src/main/resources目录下,编译后位于target/classes类路径下。 名字建议叫做mybatis-config.xml

配置文件 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 配置--> <configuration> <!--环境,很多环境,一个程序可能操作多个数据源(数据库),而且我们开发环境和本地测试环境也不一样--> <!--对于不同数据库的操作我们理解为环境--> <!--default就是程序默认使用的数据源--> <environments default="development"> <!--其中一个数据源--> <environment id="development"> <!--事务管理 jdbc--> <transactionManager type="JDBC"/> <!--数据源配置,type类型 pooled连接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <!--编码 时区--> <!--1433是sqlserver的端口号--> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?serverTimezone=UTC&amp;characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!--加载mapper映射文件--> <mappers> <!--mapper文件的全路径,注意使用/分割--> <mapper resource="com/oracle/mapper/AccountMapper.xml"/> </mappers> </configuration>

映射文件,目前放在Java下的com.oracle.mapper包下面,可以放在resource下:

AccountMapper.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 命名空间,程序中通过 sql映射的唯一标识获取 sql,比如当前文件有一个 insert sql标识,但是 其他文件中也有一个insert sql标识,就无法区分了,所以不同的sql功能,操作,使用namespce进行区分--> <!--建议namaspce的值 为 包名.文件名--> <mapper namespace="com.oracle.mapper.AccountMapper"> <!--sql代码--> <!--mybatis中提供了四个最基础的sql标签,增删改查--> <!--id是程序中获取sql的标识,完整的标识是 namespace.sqlID--> <!--resultType 结果返回类型--> <select id="selectAll" resultType="com.oracle.model.Account"> select aid,aname,apass,a_nikename as anikename from account </select> <!--通过id查询,#{} 占位符,程序会自动根据参数的类型,选择是否增加 '' --> <select id="selectByPrimayKey" resultType="com.oracle.model.Account"> select aid,aname,apass,a_nikename as anikename from account where aid = #{aid} </select> <!--下面的insert语句中 #{} 中写的是对象的属性--> <insert id="insert" > insert into account(aname,apass,a_nikename) values (#{aname},#{apass},#{anikename}) </insert> <update id="update"> update account set aname=#{aname}, apass=#{apass}, a_nikename=#{anikename} where aid = #{aid} </update> <delete id="delete"> delete from account where aid = #{aid} </delete> </mapper>

注意:

这里mappers标签还未完成,并且datasource数据源为强耦合,未拆分为properties文件。 注意事项: 在xml中配置数据源中的url属性时,当后面的连接参数有多个时,&需要转义,&amp;; 在properties中配置数据源中的url属性时,当后面的连接参数有多个时,&不需要转义。

配置文件,数据库映射文件

ORM中的O和M

o是java对象,m是配置文件

7.编写实体类

在com.oracle.model包下编写与数据库表相对应的实体类

Account.java

package com.oracle.model; /** * 实体类,mybatis建议实体类放在model包中 * 实际上你放在entity,pojo等都可以 */ public class Account { //实体类中的属性尽量都使用包装类型,因为包装类型默认值是null private Integer aid; private String aname; private String apass; //有意为之,数据库列a_nikename private String anikename; public Integer getAid() { return aid; } public void setAid(Integer aid) { this.aid = aid; } public String getAname() { return aname; } public void setAname(String aname) { this.aname = aname; } public String getApass() { return apass; } public void setApass(String apass) { this.apass = apass; } public String getAnikename() { return anikename; } public void setAnikename(String anikename) { this.anikename = anikename; } }

8.Mapper映射文件

AccountMapper.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 命名空间,程序中通过 sql映射的唯一标识获取 sql,比如当前文件有一个 insert sql标识,但是 其他文件中也有一个insert sql标识,就无法区分了,所以不同的sql功能,操作,使用namespce进行区分--> <!--建议namaspce的值 为 包名.文件名--> <mapper namespace="com.oracle.mapper.AccountMapper"> <!--查询 --> <!--sql代码--> <!--mybatis中提供了四个最基础的sql标签,增删改查--> <!--id是程序中获取sql的标识,完整的标识是 namespace.sqlID--> <!--resultType 结果返回类型--> <select id="selectAll" resultType="com.oracle.model.Account"> select * from account </select> </mapper>

先实现查询功能

Account.java实体类

package com.oracle.model; /** * 实体类,mybatis建议实体类放在model包中 * 实际上你放在entity,pojo等都可以 */ public class Account { //实体类中的属性尽量都使用包装类型,因为包装类型默认值是null private Integer aid; private String aname; private String apassword; //有意为之,数据库列a_nikename private String anikename; @Override public String toString() { return "Account{" + "aid=" + aid + ", aname='" + aname + '\'' + ", apassword='" + apassword + '\'' + ", anikename='" + anikename + '\'' + '}'; } public Account(Integer aid, String aname, String apassword, String anikename) { this.aid = aid; this.aname = aname; this.apassword = apassword; this.anikename = anikename; } public Account() { } }

结果:

[Account{aid=1, aname='zhangsan',apassword='123456', anikename='null'}, Account{aid=2, aname='lisi', apassword='123456', anikename='null'}]

表中的数据

可以看到:

结果:由于Account类的anickname和account表的a_nickname不能匹配,所以不能赋值。 所以查出来的值为null

maven管理测试类必须先用maven test,在target目录中生成编译类才可以进行测试。

从结果中可以看到,并没有封装与数据库表account中a_nickname字段不对应的anickname属性。

解决办法:用别名,因为框架在查询封装时,使用的也是别名,比如JDBC中的Metadata中的getColumnLabel()。

ResultSetMetaData metaData = resultSet.getMetaData(); String columnLabel = metaData.getColumnLabel(1); //最关键,getColumnLabel 获取字段别名,和属性一致,即可匹配

修改sql

<select id="selectAll" resultType="com.oracle.model.Account"> select aid,aname,apassword,a_nickname as anickname from account </select>

修改之后的查询结果:

[Account{aid=1, aname='zhangsan', apassword='123456', anikename='张三'}, Account{aid=2, aname='lisi', apassword='123456', anikename='李四'}]

我们发现mybatis中sql是编写在mapper.xml配置文件中的,这样做的好处是sql代码和java代码相分离,便于sql的维护,更改sql,也不需要重新编译。

在查询完毕后,mybatis自动的将查询结果和java对象进行了关联,且是集合类型。

9.根据id查询

通过id查询,#{} 占位符,程序会自动根据参数的类型,选择是否增加

AccountMapperTest2.java

package com.oracle.mapper; import com.oracle.model.Account; 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.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; public class AccountMapperTest2 { SqlSessionFactory factory = null; SqlSession sqlSession = null; @Before public void before() throws IOException { InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(in); } @Test public void selectById() { sqlSession = factory.openSession(); Account account = sqlSession.selectOne("com.oracle.mapper.AccountMapper.selectById", 1); System.out.println(account); } @After public void after() { if (sqlSession != null) { sqlSession.close(); } } }

结果:

Account{aid=1, aname='zhangsan', apassword='123456', anikename='张三'}

三.增删改

1.增

AccountMapper.xml

<!--下面的insert语句中 #{} 中写的是对象的属性--> <insert id="insert"> insert into account(aname, apassword, a_nickname) values(#{aname}, #{apassword}, #{anickname}) </insert>

AccountMapperTest.java

package com.oracle.mapper; import com.oracle.model.Account; 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 AccountMapperTest3 { @Test public void insert() throws IOException { InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); //获取sqlsession工厂 //-->sqlsession管理的工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //获取sqlsession //-->sqlsessoin是和数据库的一次会话,线程不安全,每一次会话是一个新的对象 SqlSession sqlSession = factory.openSession(); Account a = new Account(); a.setAname("wangwu"); a.setApassword("123456"); a.setAnikename("王五"); a.setAid(4); sqlSession.insert("com.oracle.mapper.AccountMapper.insert",a); //事务提交 关闭连接 sqlSession.commit(); sqlSession.close(); } }

2.改

AccountMapper.xml

<update id="update"> update account set aname = #{aname}, apassword = #{apassword}, a_nickname = #{anickname} where aid = #{aid} </update>

AccountMapperTest.java

@Test public void update() { sqlSession = factory.openSession(); Account account = new Account(); account.setAid(4); account.setAname("zhaoliu"); account.setApassword("uiloahz"); account.setAnickname("赵六"); int update = sqlSession.update("com.oracle.mapper.AccountMappe.update", account); sqlSession.commit(); }

3.删

AccountMapper.xml

<delete id="delete"> delete from account where aid = #{aid} </delete>

AccountMapperTest.java

@Test public void delete() { sqlSession = factory.openSession(); int delete = sqlSession.delete("com.oracle.mapper.AccountMappe.delete", 3); sqlSession.commit(); }

4.mapper.xml放在resources目录下

将XXXmapper.xml放在resources和DAO接口相同的目录下。

将XXXmapper.xml放在resources目录下就不用在pom.xml中设置build标签。

maven的compile命令默认会把src/main/resources下的所有配置文件以及src/main/java下的所有java文件打包或发布到target\classes下面。

最新回复(0)