一 前言

系统学习知识请认准知识追寻者(同公众号),错过作者,你有可能要走好多弯路

经过第一篇的入门文章,小白们都对mybatis的搭建流程应该都很熟悉,这篇文章主讲的是如何使用mybatis实现数据库的增删改查,以及相关的标签属性、配置说明,可以说这篇文章是为你以后的学习和工作打下坚实基础文章,小白们要认真看,认真敲,下面是准备的sql语句。此文强到没朋友!!!!

CREATE TABLE `course` (
`courseName` varchar(255) DEFAULT NULL COMMENT '课程名称',
`coursePrice` decimal(10,2) DEFAULT NULL COMMENT '课程价格',
`courseId` int(11) NOT NULL AUTO_INCREMENT COMMENT '课程id',
PRIMARY KEY (`courseId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='课程'; INSERT INTO `mybatis`.`course`(`courseName`, `coursePrice`, `courseId`) VALUES ('java基础课', 500.00, 1);
INSERT INTO `mybatis`.`course`(`courseName`, `coursePrice`, `courseId`) VALUES ('javaWeb课程', 1000.00, 2);

二 pom.xml

引入的依赖跟上篇文章一致,这次我们会用到junit单元测试。

 <dependencies>
<!-- mybatis support-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- log4j support -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- junit support -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- mysql support -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency> </dependencies>

三 log4j.properties

log4j.properties 放在 resource目录下,修改包名并配置日志级别为debug,用于打印sql;

log4j.rootLogger = info,stdout

log4j.appender.stdout = org.apache.log4j.ConsoleAppender
## 注意改薄
log4j.logger.com.zszxz.mybatis.config.mapper = debug
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

四 实体

mybatis中经常使用到实体就是可以用作封装参数或者对返回的结果集进行映射到实体;

/**
* @Author lsc
* <p> </p>
*/
public class Course { // 课程名称
private String courseName;
// 课程价格
private double coursePrice;
// 主键
private Long courseId; public String getCourseName() {
return courseName;
} public void setCourseName(String courseName) {
this.courseName = courseName;
} public double getCoursePrice() {
return coursePrice;
} public void setCoursePrice(double coursePrice) {
this.coursePrice = coursePrice;
} public Long getCourseId() {
return courseId;
} public void setCourseId(Long courseId) {
this.courseId = courseId;
}
}

五 mapper配置

mybatis-config.xml 存放于resource目录下,用于配置mybatis;

<?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"> <!-- mybaits配置 -->
<configuration> <!-- 全局环境配置-->
<environments default="development">
<environment id="development">
<!-- 事物 -->
<transactionManager type="JDBC"/>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<!-- 数据库驱动 5.6以上版本使用com.mysql.cj.jdbc.Driver -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- 数据库路径 -->
<property name="url" value="jdbc:mysql://192.168.0.105:3306/mybatis"/>
<!-- 账号-->
<property name="username" value="root"/>
<!--密码 -->
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments> <!-- 引入自定义mapper.xml 在resource 目录下 -->
<mappers>
<mapper resource="configMapper/CourseMapper.xml"/>
</mappers>
</configuration>

六 使用方法名称查询

6.1 mapper接口与mxl

这么注意命名空间与接口的关系,方法名与id的关系,返回值是类的全限定名;其中CourseMapper.xml文件是放在resource目录下configMapper中;

CourseMapper.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.zszxz.mybatis.config.mapper.CourseMapper"> <select id="getCourseList" resultType="com.zszxz.mybatis.config.entity.Course">
SELECT * FROM course
</select>
</mapper>

mapper接口

public interface CourseMapper {

    /* *
* @Author lsc
* <p> 查询课程列表</p>
* @Param []
* @Return java.util.List<com.zszxz.mybatis.config.entity.Course>
*/
List<Course> getCourseList(); }

6.2查询测试

这边的@before注解是在每次执行测试类之前都会执行,固后面的查询测试将直接列出测试方法,不会重复@before注解下的方法;

@RunWith(JUnit4.class)
public class SelectTest { SqlSession sqlSession = null; // @Before 会在执行测试类之前执行该方法
@Before
public void before() throws IOException {
// 资源路径 resource目录下
String resource = "mybatis-config.xml";
// 配置mybatis获得输入流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//从 SqlSessionFactory 中获取 SqlSession
sqlSession= sqlSessionFactory.openSession();
}
/* *
* @Author lsc
* <p> 查询课程列表</p>
* @Param []
* @Return void
*/
@Test
public void testSelect(){
// 使用传入方法名查询形式
List<Course> getCourseList = sqlSession.selectList("getCourseList");
for (Course course : getCourseList){
System.out.println(course.getCourseName());
}
sqlSession.close();
}
}

6.3 测试结果

==>  Preparing: SELECT * FROM course
[DEBUG] 2019-12-05 21:02:00,238 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters:
[DEBUG] 2019-12-05 21:02:00,256 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Total: 2
java基础课
javaWeb课程

七 使用获取接口方式查询

这种方式是主流方式,你不可能每次查询都输入一个方法名吧,很不现实,我们更倾向于面向对象方式直接调用方法获得想要的结果;

7.1 查询测试

测试结果和上次一致;

 @Test
public void testSelect2(){
// 获得mapper的形式
CourseMapper courseMapper = sqlSession.getMapper(CourseMapper.class);
// 遍历打印课程
for (Course course : courseMapper.getCourseList()){
System.out.println(course.getCourseName());
}
sqlSession.close();
}

7.2 select标签属性说明

属性 说明
id 在命名空间中唯一的标识符,可以代表引用该sql
parameterType 入参的完全限定名或者别名,可选操作,默认未设置。
resultType 返回值的期望类型的类的完全限定名或者别名,可以使用 resultType 或 resultMap,但不能同时使用
resultMap 外部结果集映射配置,可以与实体字段映射;可以使用 resultType 或 resultMap,但不能同时使用
flushCache 设置true会清口本地缓存和二级缓存,默认是false
useCache 设置为true会导致查询结果集保存至二级缓存,对于select默认是true
timeout 抛出异常前,驱动程序等待的最大毫秒数,默认未设置,依赖于驱动
fetchSize 驱动程序每次批量返回行数,默认未设置
statementType 设置STATEMENT,PREPARED 或 CALLABLE 。分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED
resultSetType 设置结果集类型,FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset)默认为设置 DEFAULT
databaseId 如果配置了数据库厂商标识(databaseIdProvider),会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
resultOrdered 嵌套查询语句中使用,设置为true,则sql执行结果为嵌套结果或者分组
resultSets 在多个结果集情况下,会列出结果集名称,以逗号分隔

八 普通新增

8.1 mapper接口方法

    /* *
* @Author lsc
* <p> 普通新增</p>
* @Param [course]
* @Return int
*/
int addCourse(Course course);

8.2 mxl语句

    <insert id="addCourse" parameterType="com.zszxz.mybatis.config.entity.Course">
INSERT INTO course ( courseName, coursePrice ) VALUES ( #{ courseName },#{ coursePrice });
</insert>

8.3 测试

 @Test
public void testInsert(){ // 创建入参实体 Course
Course course = new Course();
course.setCourseName("知识追寻者的心理课");
course.setCoursePrice(10000);
// 获得mapper
CourseMapper courseMapper = sqlSession.getMapper(CourseMapper.class);
// 调用添加课程方法
courseMapper.addCourse(course);
// 事物提交
sqlSession.commit();
// 关闭会话
sqlSession.close();
}

8.4 执行结果

可以看见我们用#{}在xml中达到了原生jdbc预编译后的结果每次进入都是以?占位符形式,有效防止sql注入问题;${}通常用在获取字段名称,表名,而非入参,否则会有sql注入风险。

[DEBUG] 2019-12-05 21:58:44,193 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Preparing: INSERT INTO course ( courseName, coursePrice ) VALUES ( ?,?);
[DEBUG] 2019-12-05 21:58:44,221 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters: 知识追寻者的心理课(String), 10000.0(Double)
[DEBUG] 2019-12-05 21:58:44,224 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Updates: 1

九 新增返回主键方式一

9.1 mapper接口方法

    /* *
* @Author lsc
* <p> 新增数据并获得主键方式1</p>
* @Param [course]
* @Return int
*/
int addCourseAndGetIdbyGen(Course course);

9.2 mxl语句

<insert> 标签中 相比于 <select> 标签多出了3个属性。

  1. useGeneratedKeys 为true,表示使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键。其适用于mysql 、 sqlServer这样有自增主键的数据库管理系统,默认是false;仅对 插入和更新操作有效。
  2. keyProperty 代表主键,mybaits会将主键赋值给这个列,这里我们配置的是实体字段courseId;希望赋值给多个列,默认是以逗号分开;默认是未设置;仅对 插入和更新操作有效。
  3. keyColumn 当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。我们这里必须设置,因为作者把 主键放在第三列了,不仔细看作者文章的小朋友等着出错把!默认是未设置;仅对 插入和更新操作有效。
   <insert id="addCourseAndGetIdbyGen" parameterType="com.zszxz.mybatis.config.entity.Course" useGeneratedKeys="true" keyProperty="courseId" keyColumn="courseId">
INSERT INTO course ( courseName, coursePrice ) VALUES ( #{ courseName },#{ coursePrice });
</insert>

9.3 测试

小白们这里注意啊,获得插入的主键是从我们入参的Course实体属性中获得;

    @Test
public void testInsertGetId1(){ Course course = new Course();
course.setCourseName("知识追寻者的课程1");
course.setCoursePrice(100000);
CourseMapper courseMapper = sqlSession.getMapper(CourseMapper.class);
courseMapper.addCourseAndGetIdbyGen(course);
//
System.out.println("返回的课程id: "+course.getCourseId());
sqlSession.commit();
sqlSession.close();
}

9.4 执行结果

[DEBUG] 2019-12-05 22:17:01,788 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Preparing: INSERT INTO course ( courseName, coursePrice ) VALUES ( ?,?);
[DEBUG] 2019-12-05 22:17:01,820 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters: 知识追寻者的课程1(String), 100000.0(Double)
[DEBUG] 2019-12-05 22:17:01,822 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Updates: 1
返回的课程id: 4

十新增返回主键方式二

10.1 mapper接口方法

    /* *
* @Author lsc
* <p> 新增数据并获得主键方式2</p>
* @Param [course]
* @Return int
*/
int addCourseAndGetIdbyKey(Course course);

10.2 mxl语句

这里使用了 <selectKey> 标签做返回插入数据的主键,这种方式使用于具有主键自增的数据库管理系统,也使用于像oracle这样不具有主键自增的数据库管理系统,而且每种数据库管理系统支持的 <selectKey> 标签内容都不一样,但都大同小异,读者可以查阅数据库管理系统相关文档使用。需要注意的是 order 属性,由于mysql这种主键自增型数据库管理系统是语句插入后才能获得主键,固使用 after;如果是 oracle这种非自增型主键数据库管理系统,是语句插入之前主键就以及存在,固要设置属性为before;

    <insert id="addCourseAndGetIdbyKey" parameterType="com.zszxz.mybatis.config.entity.Course">
INSERT INTO course ( courseName, coursePrice, courseId ) VALUES ( #{ courseName },#{ coursePrice },#{ courseId });
<selectKey resultType="long" order="AFTER" keyProperty="courseId">
SELECT LAST_INSERT_ID();
</selectKey>
</insert>

10.3 测试

代码很清秀,不用作者多余的注释了吧。

	 @Test
public void testInsertGetId2(){ Course course = new Course();
course.setCourseName("知识追寻者的课程2");
course.setCoursePrice(100000);
CourseMapper courseMapper = sqlSession.getMapper(CourseMapper.class);
courseMapper.addCourseAndGetIdbyGen(course);
//
System.out.println("返回的课程id: "+course.getCourseId());
sqlSession.commit();
sqlSession.close();
}

10.4 执行结果

[DEBUG] 2019-12-05 22:25:31,232 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Preparing: INSERT INTO course ( courseName, coursePrice ) VALUES ( ?,?);
[DEBUG] 2019-12-05 22:25:31,258 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters: 知识追寻者的课程2(String), 100000.0(Double)
[DEBUG] 2019-12-05 22:25:31,261 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Updates: 1
返回的课程id: 5

十一更新操作

更新相比于查询和插入,其相对简单;

11.1 mapper接口方法

    /* *
* @Author lsc
* <p> </p>
* @Param [course]
* @Return int
*/
int updateCourse(Course course);

11.2 mxl语句

    <update id="updateCourse" parameterType="com.zszxz.mybatis.config.entity.Course">
UPDATE course set courseName = #{courseName}, coursePrice = #{coursePrice}
WHERE courseId = #{courseId}
</update>

11.3 测试

    @Test
public void testUpdate2(){ Course course = new Course();
course.setCourseName("知识追寻者的课程3");
course.setCoursePrice(1000);
course.setCourseId(5L);
CourseMapper courseMapper = sqlSession.getMapper(CourseMapper.class);
courseMapper.updateCourse(course);
sqlSession.commit();
sqlSession.close();
}

11.4 执行结果

[DEBUG] 2019-12-05 22:38:46,093 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Preparing: UPDATE course set courseName = ?, coursePrice = ? WHERE courseId = ?
[DEBUG] 2019-12-05 22:38:46,121 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters: 知识追寻者的课程3(String), 1000.0(Double), 5(Long)
[DEBUG] 2019-12-05 22:38:46,124 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Updates: 1

十二删除操作

删除操作和更新操作类似,没什么技巧难度;

12.1 mapper接口方法

    /* *
* @Author lsc
* <p> </p>
* @Param []
* @Return int
*/
int deleteCourse(Long courseId);

12.2 mxl语句

    <delete id="deleteCourse" parameterType="long">
DELETE FROM course WHERE courseId = #{courseId}
</delete>

12.3 测试

    @Test
public void testDelte(){ CourseMapper courseMapper = sqlSession.getMapper(CourseMapper.class);
courseMapper.deleteCourse(1L);
sqlSession.commit();
sqlSession.close();
}

12.4 执行结果

[DEBUG] 2019-12-05 22:39:29,926 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Preparing: DELETE FROM course WHERE courseId = ?
[DEBUG] 2019-12-05 22:39:29,952 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
==> Parameters: 1(Long)
[DEBUG] 2019-12-05 22:39:29,955 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)
<== Updates: 1

十三 参考文档

mybatis官方文档

mybatis初级映射的更多相关文章

  1. MyBatis初级实战之一:Spring Boot集成

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  2. MyBatis初级实战之二:增删改查

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. MyBatis初级实战之三:springboot集成druid

    OpenWrite版: 欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kuber ...

  4. MyBatis初级实战之四:druid多数据源

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  5. MyBatis初级实战之五:一对一关联查询

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. MyBatis初级实战之六:一对多关联查询

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. 【Mybatis高级映射】一对一映射、一对多映射、多对多映射

    前言 当我们学习heribnate的时候,也就是SSH框架的网上商城的时候,我们就学习过它对应的高级映射,一对一映射,一对多映射,多对多映射.对于SSM的Mybatis来说,肯定也是差不多的.既然开了 ...

  8. MyBatis 关系映射XML配置

    关系映射 在我看来这些实体类就没啥太大关联关系,不就是一个sql语句解决的问题,直接多表查询就完事,程序将它设置关联就好 xml里面配置也是配置了sql语句,下面给出几个关系的小毛驴(xml) 一对多 ...

  9. mybatis高级映射(一对一,一对多)

    mybatis高级映射 一对一关联映射 需求:查询订单信息,关联查询用户信息(一个订单对应一个用户) (1)通过resultType实现 sql语句: select orders.* , USER.u ...

随机推荐

  1. 标准库bufio个人详解

    本文是我有通俗的语言写的如果有误请指出. 先看bufio官方文档 https://studygolang.com/pkgdoc文档地址 主要分三部分Reader.Writer.Scanner 分别是读 ...

  2. Kibana创建索引成功,但一直不显示出来(Fielddata is disabled on text fields by default. Set fielddata=true........)

    现象 把EFK整个集群搭建完成后,通过Kibana操作界面创建索引(如图1),我创建了lile-zabbix*的索引,显示是创建成功了,但是只要我在重新刷新一次,已经创建的索引就“消失了”.后通过查看 ...

  3. (三十六)golang--文件的基本操作

    文件程序中是以流的形式操作的. 流:数据在数据源(文件)和程序(内存)之间经历的路径: 输入流:数据从数据源到程序的路径: 输出流:数据从程序到数据源的路径: 常用的文件操作和函数: 1.常用的文件操 ...

  4. GeoServer 安装教程

    准备内容 安装环境:win10*64位专业版 安装文件:geoserver-2.15.2 安装步骤 安装JDK 1.安装GeoServer是基于Java的环境,所以需要先装Jdk环境. 2.前往官网下 ...

  5. React中使用create-react-app创建项目,运行npm run eject建立灰度报错

    我在运行npm run eject建立测试环境和正式环境时候报错 这里的问题是是脚手架添加.gitgnore文件,但是却没有本地仓库,按照以下顺序就可以正常使用 git add . git commi ...

  6. C#音频截取与原文匹配

    1.需求 上传一个音频文件(例如英语听力的音频)与音频对应的原文word文档.大概估算音频中一段对话到另一端对话的时间间隔,将音频截取为不同对话的小音频文件,通过百度语音识别转换成英文,然后与原文对比 ...

  7. 2019-10-16:maccms10后门复现利用,解析

    该文章仅供学习,利用方法来自网络文章,仅供参考 Maccms10基于php+mysql的maccms,是苹果的内容管理,方便使用,功能良好,适用范围广 后门网站下载网址,是假官网:http://www ...

  8. 10分钟学会Python函数基础知识

    看完本文大概需要8分钟,看完后,仔细看下代码,认真回一下,函数基本知识就OK了.最好还是把代码敲一下. 一.函数基础 简单地说,一个函数就是一组Python语句的组合,它们可以在程序中运行一次或多次运 ...

  9. 1、Docker 简介

    目录 Docker 起源 Docker 架构 特性 局限 名称空间隔离 原理 Control Groups (cgroups) Docker Docker 啥是docker? Docker 是一个开源 ...

  10. 从壹开始 [ Design Pattern ] 之三 ║ 工厂模式 与 小故事

    编者按: 定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使得一个类的实例化延迟到子类. 工厂模式,是迄今为止,使用最多,最广泛的设计模式之一,它的身影几乎出现在每一个框架和个人代码之中 ...