系列文章目录
MyBatis01:创建、运行、测试一个mybatis项目
MyBatis02:使用MyBatis查询数据
MyBatis03:嵌套查询、嵌套结果、延迟加载
MyBatis04:动态SQL
MyBatis05:类型转换器
MyBatis06:分页插件、MyBatis配置文件中的标签
MyBatis07:MyBatis注解
前言
本文是一篇mybatis的入门文章。从一个入门的角度,介绍mybatis环境搭建,项目创建、运行和测试的学习笔记。使用的软件的是idea2020.3.3。
一、框架简介
框架都有侧重点,具体实现的功能不同。下面简单的介绍一下SSH框架和SSM框架的作用。
- SSH框架
框架名 | 作用 |
---|---|
spring | 用来整合框架 |
struct2 | 简化web操作,替代Servlet |
hibernate | 简化dao层 |
- SSM框架
框架名 | 作用 |
---|---|
spring | 用来整合框架 |
SpringMVC | 简化web操作,替代Servlet |
mybatis | 简化dao层 |
1. 什么是mybatis,有什么作用
mybatis是一个持久型框架,半自动ORM。能够简化持久层(dao层)的代码。
1.1 什么是持久型
持久说的是数据能否持久保存。如果数据是保存在硬盘或数据库中,数据就是持久的。如果数据是保存在内存中,就是非持久的。
1.2 什么是半自动
半自动化就是dao层的操作不全是由框架生成的,这里我们还需要自己写SQL语句,这是相对于全自动化的 hibernate框架
而言的。hibernate
连SQL语句都不用写,全是由框架生成,但是配置过于繁琐。由于多数情况下还是需要我们自己写SQL语句的,比较灵活,而且 mybatis
的配置较为简单,故使用 mybatis
框架的还是比较多。
1.3 什么是ORM
O是object对象,R是Relational关系型,M是mapping映射,就是能将数据库字段和实体层属性建立起对应关系的这么一种框架。
2. ibatis和mybatis的联系
ibatis是mybatis的前身。ibatis的3的版本就是mybatis。
3. mybatis项目与普通的javaweb项目的区别
mybatis项目主要的作用就是简化dao层操作。那它是怎么简化dao层操作的呢?我们之前写的javaweb项目,在写dao层的时候,我们需要加载驱动、创建连接对象、创建预处理对象、需要用ResultSet接受返回值等一系列JDBC操作,自从用了 mybatis
我们都不需要写了。你需要做的只有写好配置文件和SQL语句即可,这就是mybatis存在的意义。
二、创建一个mybatis项目
首先要介绍一下工作区,当然创建mybatis项目和工作区是没有必然联系的。建立工作区的主要目的就是为了方便我们查看和管理项目。idea里是没有工作区的概念的,不像eclipse。在eclipse里,你写过的所有项目都可以在左侧的项目列表中显示,要查看哪个项目直接点开就可以了,很是方便。在idea中建立工作区后,将子项目都添加到大项目中,这样查看这些子项目就比较方便,不用单独打开一个个工程。
1. 创建一个大项目
工作区的作用就是用来聚合项目的。然后在工作区下新建子项目,子项目就是我们的工程,用来写代码,实现某方面的功能。
- 首先先建一个工作区,创建的是一个简单的Java项目,用来聚合子项目。
下一步
设置项目名
2. 建立子项目
子项目就是一个个Module,用来写子项目的代码,实现某方面的功能。
设置子项目的名称
3. 创建一个lib文件夹
lib文件夹是用来存放运行mybatis框架的jar包。
jar包如下:
添加后换需要 Add as Library,让项目识别这些依赖。
ok即可。
4. 添加mybatis框架的配置信息
在src文件夹下创建mybatis.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>
<!--指定使用的是哪个配置源(配置源id),可以写多个配置源-->
<environments default="development">
<!--这是其中一个配置源,配置源id是development,可以添加多个配置源-->
<environment id="development">
<transactionManager type="JDBC" />
<!--数据源-->
<dataSource type="POOLED">
<!--具体配置,name是固定的,需要修改的只有value值-->
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<!--连接哪个数据库,需要改为要连接的数据库名字mybatis-->
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 " />
<!--数据库的用户名-->
<property name="username" value="root" />
<!--数据库的密码-->
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!--这里添加dao层映射文件的路径,这样项目才能识别这个映射配置-->
<mappers>
<mapper resource="com/mapping/ClazzMapper.xml" />
</mappers>
</configuration>
5. 添加日志的属性文件
添加后,可用来打印日志信息。添加该文件后,换需要重启一下软件,该日志文件才能生效。
三、运行项目
连接数据库(方便查看数据库字段)
1. bean层
1.1 Clazz.java
package com.bean;
public class Clazz {
private int id;
private String classname;
// 构造方法
public Clazz() {
}
public Clazz(int id, String classname) {
this.id = id;
this.classname = classname;
}
// 属性封装
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
}
2. 数据访问层——dao包+mapping包
面向接口编程。dao+mapping构成数据访问层。
2.1 dao包——ClazzMapper接口
这里只写接口即可,由映射文件来实现功能。
package com.dao;
import com.bean.Clazz;
import java.util.List;
public interface ClazzMapper {
/*框架默认将参数以特殊结构存入map集合*/
/*映射文件xml里,通过ognl表达式来获取map里的值进行使用——#{key}*/
/*参数如果是一个并且是对象,默认对象的属性名和属性值作为key-value存入map*/
int insert(Clazz clazz);
int insertSelective(Clazz clazz);
int updateByPrimaryKey(Clazz clazz);
int updateByPrimaryKeySelective(Clazz clazz);
int delete(Integer deptno);
Clazz selectByPrimaryKey(Integer deptno);
List<Clazz> selectAll();
}
2.2 mapping包——ClazzMapping.xml 配置
这是映射文件。在mapping包创建 ClazzMapping.xml
文件后,还需要在框架的配置文件 mybatis.xml
文件里添加映射,如下:
ClazzMapping.xml 代码
- 相关解释:
属性名 | 含义 / 作用 |
---|---|
namespace | 是命名空间,指定捆绑的接口的路径 |
parameterType | 是方法参数的数据类型,可以不写 |
keyProperty | bean层属性名 |
keyColumn | 数据库字段 |
resultType | 返回值类型,用于select查询 |
order | 是SQL语句执行顺序,before是在插入语句之前执行 |
- 注意:
①增删改不用写方法返回值的数据类型,默认是int
②sql语句后不能写 ;
③映射文件xml里,通过ognl表达式来获取map里的值进行使用——#{key}
<?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是命名空间,指定捆绑的接口的路径-->
<mapper namespace="com.dao.ClazzMapper">
<!--自动获取生成的主键有两种方式:一、db支持自动增长的可以使用useGenerateKeys-->
<!--<insert id="insert2" parameterType="com.bean.Clazz" useGeneratedKeys="true" keyProperty="id" keyColumn="id">>
insert into clazz(classname) values (#{classname})
</insert>-->
<!--自动获取生成的主键有两种方式:二、db不支持自动增长的可以使用selectKey-->
<!--主键不是自动增长时,可以通过查询的方式来获取主键值-->
<insert id="insert">
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="BEFORE">
select max(id) + 1 from clazz
</selectKey>
insert into clazz(id, classname) values (#{id}, #{classname})
</insert>
<update id="updateByPrimaryKey">
update clazz set classname = #{classname} where id = #{id}
</update>
<delete id="delete">
delete from clazz where id = #{id}
</delete>
</mapper>
3. 业务逻辑层——service包
3.1 ClazzService接口
面向接口编程。这里只写接口,由实现类来写具体功能。
package com.service;
import com.bean.Clazz;
import java.util.List;
public interface ClazzService {
int insert(Clazz clazz);
int insertSelective(Clazz clazz);
int updateByPrimaryKey(Clazz clazz);
int updateByPrimaryKeySelective(Clazz clazz);
int delete(Integer deptno);
Clazz selectByPrimaryKey(Integer deptno);
List<Clazz> selectAll();
}
3.2 ClazzServiceImpl类
是ClazzService接口的实现类,用来实现接口里方法的功能。
3.2.1 如何在Service的实现类里实例化dao对象
- 声明dao接口引用
- 以流的形式加载主配置文件
- 新建会话工厂,构建主配置文件
- 通过会话工厂建立会话,创建核心处理类,SqlSession对象
- 通过SqlSession对象建立起某个类的映射关系
package com.service;
import com.bean.Clazz;
import com.dao.ClazzMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class ClazzServiceImpl implements ClazzService{
// dao层接口对象
private ClazzMapper clazzMapper;
public ClazzServiceImpl() {
// 目的是想为clazzMapper赋值,启动mybatis框架获取dao层接口的实现类对象,核心处理类sqlSession
try {
// 1.读取mybatis主配置文件
InputStream is = Resources.getResourceAsStream("mybatis.xml");
// 2.创建session工程
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// 3.获取核心处理类SqlSession对象
SqlSession session = factory.openSession(true);
this.clazzMapper = session.getMapper(ClazzMapper.class);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public int insert(Clazz clazz) {
return this.clazzMapper.insert(clazz);
}
@Override
public int insertSelective(Clazz clazz) {
return 0;
}
@Override
public int updateByPrimaryKey(Clazz clazz) {
return this.clazzMapper.updateByPrimaryKey(clazz);
}
@Override
public int updateByPrimaryKeySelective(Clazz clazz) {
return 0;
}
@Override
public int delete(Integer deptno) {
return this.clazzMapper.delete(deptno);
}
@Override
public Clazz selectByPrimaryKey(Integer deptno) {
return null;
}
@Override
public List<Clazz> selectAll() {
return this.clazzMapper.selectAll();
}
}
4. 测试层——test包
4.1 ClazzTest类
使用了@Test注解。添加测试代码后,直接点运行即可测试。
package com.test;
import com.bean.Clazz;
import com.service.ClazzService;
import com.service.ClazzServiceImpl;
import org.junit.Test;
public class ClazzTest {
// 用实现类ClazzServiceImpl实例化ClazzService接口
private ClazzService clazzService = new ClazzServiceImpl();
// 测试添加班级的方法
@Test
public void testInsert() {
// 创建Clazz对象,调用clazzService的insert方法插入数据
Clazz clazz = new Clazz(1, "class002");
System.out.println(clazzService.insert(clazz));
System.out.println(clazz.getId());
}
// @Test
// public void testUpdate() {
// Clazz clazz = new Clazz(1, "class111");
// System.out.println(clazzService.updateByPrimaryKey(clazz));
// System.out.println(clazz.getClassname());
// }
// @Test
// public void testDelete() {
// System.out.println(clazzService.delete(4));
// }
}
四、对于映射层的总结
1. 自问自答
1.1 dao层接口和mapper映射如何建立起联系
是通过映射文件里的 namespace="dao层接口路径"
将dao层接口和mapper映射捆绑起来
<mapper namespace="com.dao.ClazzMapper">
这里面写SQL语句
</mapper>
1.2 接口里的方法如何与映射文件的元素绑定
①标签名就是要实行的SQL操作
②id=“接口里的方法名”
是通过id将接口里的方法与映射文件的元素绑定的。
<insert id="insert2" parameterType="com.bean.Clazz" useGeneratedKeys="true" keyProperty="id" keyColumn="id">>
insert into clazz(classname) values (#{classname})
</insert>
1.3 mybatis接口类的方法不能重载
①首先要声明的是接口里的方法是可以重载的,只是mybatis接口里的方法不能重载
②根据1.2问题,我们知道接口里的方法和映射文件的元素绑定是通过方法名来绑定的。如果对mybatis接口类里的方法进行重载的话,就会产生冲突,程序就不知道自己绑定的到底是哪一个重载的方法,程序要执行哪一个重载方法。
1.4 SQL语句如何获取参数
系统将方法里的参数保存到map里,框架使用ognl表达式获取参数。
ognl表达式:#{key}。
注意:#{}表达式自带引号,想这样"#{}"
1.5 参数的获取
①参数类型是8种基本数据类型或String类型,参数名和参数值就是键值
②参数是一个对象。对象的属性名和属性值就是键值。
1.6 insert语句,如何让主键自动生成,并让主键的值能回填到属性里
①数据库的主键自动增长:使用 useGeneratedKeys
属性
<insert id="insert" parameterType="com.bean.Clazz" useGeneratedKeys="true" keyProperty="id" keyColumn="id">>
insert into clazz(classname) values (#{classname})
</insert>
属性 | 作用 |
---|---|
useGeneratedKeys | 取出由数据库内部生成的主键 |
keyProperty | 指定能够唯一识别对象的属性 |
keyColumn | 设置生成键值在数据库表中的列名 |
通过这三个属性就可以建立起数据库和实体层的联系。利用的是数据库的主键的自动增长,让主键的值能回填到属性里,从而实现插入数据的主键自动增长。 |
②数据库的主键不自动增长:使用 selectKey
标签
<insert id="insert">
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="BEFORE">
select max(id) + 1 from clazz
</selectKey>
insert into clazz(id, classname) values (#{id}, #{classname})
</insert>
属性 | 作用 |
---|---|
keyProperty | 指定能够唯一识别对象的属性 |
keyColumn | 设置生成键值在数据库表中的列名 |
resultType | 返回值类型,用于select查询结果(非空) |
order | 语句的执行顺序,before是在insert语句之前执行 |
通过查询当前数据库中记录的条数,来确定新插入的记录的主键值,让主键的值能回填到属性里,从而实现插入数据的主键的自动增长。 |
③使用useGeneratedKeys和selectKey都可以实现主键自动增长,都不需要自己设定id值。传递的参数都是Clazz对象,一个是由数据库的自动增长实现;一个是由查询结果得到id值。
1.7 mybatis的核心处理对象
SqlSession(后续记录)
2. 遇到的问题
2.1 插入语句注意
插入语句时,对象的属性和数据库的列名一一对应,列名别忘记写了
否则可能会报 列名不对应
的错误
总结
今天入门了mybatis框架,简单的了解了各个框架的作用,明确了各个框架的侧重点。创建、配置、运行、测试了第一个mybatis项目。目前增删改都是可以正常运行的。