【MyBatis】Java 持久层框架入门与实践

您所在的位置:网站首页 mybatis框架特点和核心功能 【MyBatis】Java 持久层框架入门与实践

【MyBatis】Java 持久层框架入门与实践

2024-07-17 02:46| 来源: 网络整理| 查看: 265

Java 持久层框架入门与实践 | 学习笔记 导读

本篇文章将带领读者学习 MyBatis 框架。开始文章简述 MyBatis。之后将手把手的搭建一个简单的 MyBatis 框架的测试,先跑起来。随后将基于该测试讲解 MyBatis 框架中重要的几个配置文件。然后对于数据库常用的增、删、查、改操作在 MyBatis 中的进行实现,并讨论一些 Java 中集合在 MyBatis 中的配置与应用。剩下的时间将讲解一些细节而常用的知识。

文中代码中嵌有大量的注释,这些注释对于理解和学习 MyBatis 有巨大的作用,请不要因为页面显示的字体颜色不清晰而忽略掉它们。

文中的测试与运行环境为:Java 8,IDEA 2020,Maven3.6.1,MyBatis 3.4.6,Mysql 8.0.15,Windows 10。 请格外留意 Mysql 的版本,低于 Mysql 8 的 mybatis-config.xml 配置将与本文中的配置不同

文章目录 Java 持久层框架入门与实践 | 学习笔记导读一. MyBatis 简介二. 现有的持久化技术三. MyBatis 项目搭建过程四. mybatis-config.xml 文件配置操作五. 数据库的增、删、改、查、操作六. MyBatis 获取参数的两种方式七. 获取自动生成的主键相关链接

一. MyBatis 简介 MyBatis 是支持定制化 SQL、存储过程、高级映射的优秀持久层框架MyBatis 避免了几乎所有的 JDBC 代码或手动设置参数以及获取结果集MyBatis 可以使用简单的 XML 或注释用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,即普通的 Java 对象)映射成数据库中的记录MyBatis 是一个半自动的 ORM (Object Relation Mapping)框架 二. 现有的持久化技术 JDBC SQL 夹在 Java 代码里,耦合度高导致硬编码内伤维护不易切实际开发需求中 SQL 有变化,修改频繁 Hibernate 和 JPA 长难 SQL,对于 Hibernate 而言处理也不容易内部自动生成 SQL,不容易做特殊优化基于全映射的自动框架,大量字段的 POJO 进行部分映射比较困难。导致数据库性能下降 MyBatis 对于开发人员而言,核心 SQL 依然需要自己优化SQL 和 Java 编码分开,功能边界清晰,一个专注业务,一个专注数据,更好的解耦合 三. MyBatis 项目搭建过程

添加 Maven 依赖(或者导入 jar 包)

org.mybatis mybatis 3.4.6 compile mysql mysql-connector-java 8.0.15

注意搭建 MyBatis 项目,需要另外添加 JDBC 依赖(或导入 JDBC 的 jar 包),本文中使用 Mysql 的 JDBC

创建 MyBatis 的核心(全局)配置文件 mybatis-config.xml

该配置文件在 Maven 项目中在 resource 目录下 配置以MySQL为数据库为例

创建映射文件 XxxMapper.xml,并配置

在 MySQL 数据库简单创建一个测试数据库:

User表:

uiduserNamepasswordagesex1admin12345623男

在 Maven 项目的 resources 目录下创建映射文件 UserMapper.xml

select * from User where uid = #{id}

创建 mapper 接口,实现两个绑定

UserMapper.xml 实现了两个绑定

接口全限定名要和映射文件的命名空间( 标签的 namespace 属性)保持一致接口中的方法名和 SQL 语句的 id ( 标签的属性)保持一致,返回值与 resultType( 标签的属性) 一致

UserMapper.xml 中涉及到的类资源与映射接口如下

User.java 实体类

package org.example; public class User { private Integer uid; private String userName; private String password; private Integer age; private String sex; public User() {} public User(String uid, String userName, String password, Integer age, String sex) { this.uid = uid; this.userName =userName; this.password = password; this.age = age; this.sex = sex; } public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "User{" + "uid=" + uid + ", userName='" + userName + '\'' + ", password='" + password + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}'; } }

UserMapper.java 映射接口

package org.example.Mapper; import org.example.Bean.User; public interface UserMapper { User getUserByUid(int uid); }

获取 MyBatis 操作数据库的会话对象 sqlSession 与测试

简单的测试当前的程序,过程中获取 sqlSession 对象

package org.example.Main; 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.example.Bean.User; import org.example.Mapper.UserMapper; import java.io.IOException; import java.io.InputStream; public class run { public static void main(String[] args) throws IOException { //将资源开启为 inputstream 对象,加载全局配置文件 InputStream input = Resources.getResourceAsStream("mybatis-config.xml"); //以全局配置文件作为参数,使用 SqlSessionFactoryBuilder 建造一个 SqlSessionFactory 对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input); //以 SqlSessionFactory 文件创建一个 SqlSession 对象 //参数true表示事务将会自动提交 SqlSession sqlSession = sqlSessionFactory.openSession(true); //使用 Sqlsession 创建映射关系对象 //getMapper() 会通过动态代理动态生成UserMapper的代理实现类 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //调用映射关系对象的方法,进行查询 User user = userMapper.getUserByUid(1); System.out.println(user); } }

运行结果

User{uid=1, userName='admin', password='123456', age=23, sex='男'}

查询成功

注意

UserMapper 是一个接口,显然是无法实例化的,此处的 userMapper 对象时一个实现了 UserMapper 的类的对象。而这个类的具体实现是由 MyBatis 完成的。

总结

项目文件梳理 在这里插入图片描述 上述案例中一共创建了四个文件:mybatis-config 核心配置文件、UserMapper 映射配置文件、UserMapper 映射接口、User 实体类。目前,他们之间的联系、关联如图所示。mybatis-config 文件还记录了数据库相关的信息。

MyBatis 实现的映射

在这里插入图片描述 文章在前介绍过 MyBatis —— 可以将接口和 Java 的 POJO(Plain Old Java Objects,即普通的 Java 对象)映射成数据库中的记录。本例中,MyBatis 就实现了这种映射。User 是做为 Entity 实体。UserMapper 映射接口做为 DAO。

四. mybatis-config.xml 文件配置操作

标签的使用

在 标签下书写 标签。指定 properties 配置。

此时 标签的属性可修改

... ...

标签相当于定义了一个键值对,name 属性 jdbc.driver 为键,value 属性为值,在该定义后,可在标签下文中使用${jdbc.driver}通过键取得值。

标签与 .properties 资源文件联用

在项目的 resource 目录下创建 .properties 资源文件,并在全局配置文件中使用。

jdbc.properties

jdbc.driver = com.mysql.cj.jdbc.Driver jdbc.url = jdbc:mysql://127.0.0.1:3306/mybatistest?useUnicode=true;characterEncoding=UTF-8;userSSL=false;serverTimezone=GMT%2B8 jdbc.username = root jdbc.password = 123456

在全局配置文件中引入 properties 文件

在引入外部资源文件后,在全局配置中 标签下可以进行修改为

此方法使用 .properties 文件更有利于解耦合与后续的项目修改。.properties 资源文件的可读性与易修改性比 .xml 文件强

标签的使用

在全局配置文件中使用 标签能够实现一些功能

例如:

因为数据库的字段命名尝用下划线分开单词,例如本例中使用 userName 为实体类,并且数据库中的字段名也为 userName,若不同,例如数据库字段为 user_name,则读取 userName 数据值将会为 null,产生错误的结果。 而该设置可以避免这一问题,将数据库的下划线字段名自动识别为驼峰式的命名,并读取数据。

本文仅介绍这一功能,其他功能可参见 MyBatis 文档

标签的使用

为一个 Java 类设置一个更短的名称

默认的类别名设置

此时在映射文件中,如 UserMapper.xml 可以修改类名称为

select * from User where uid = #{id}

指定别名以设置别名

此时在映射文件中,如 UserMapper.xml 可以修改类名称为

select * from User where uid = #{id}

标签包批量别名

在 org.example.bean 下的所有类全部设置为默认别名

五. 数据库的增、删、改、查、操作

对于数据库的增删改查操作需要书写映射接口,与 Mapper 映射文件。

映射接口

package org.example; public interface UserMapper { //通过uid获取用户对象 User getUserByUid(int uid); //增加用户 void addUser(User user); //更新,修改用户 void updateUser(User user); //删除用户 void deleteUser(int uid); //获取用户数量 Integer getCount(); //获取全体用户对象 List getAllUser(); //设置 map 的键,因为在查询时传出所有员工的信息,可以把员工信息作为值,但是必须设置键 @MapKey("uid") Map getAllUserMap(); //以 map 集合获取一个员工信息 @MapKey("uid") Map getUserMapByUid(String uid); } 返回值为 void 的方法也可以设置返回值为 Integer 或 Boolean,Integer 类型表示多少行受影响,Boolean 类型表示是否影响到行。

UserMapper.xml 映射文件

select * from User where uid = #{id} insert into user value(null,#{uid},#{user_name},#{password},#{age},#{sex}) update user set user_name = #{user_name}, age = #{age}, sex = #{sex} where uid = #{uid} delete from user where uid = #{uid} select count(uid) from user select * from user select * from user select * from user where uid = #{uid}

执行测试

package org.example.Main; 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.example.Bean.User; import org.example.Mapper.UserMapper; import java.io.IOException; import java.io.InputStream; public class run { public static void main(String[] args) throws IOException { InputStream input = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input); //注意,与前一个案例不同,此处没有填入参数true。因此事务需要手动提交 SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //添加用户的操作 userMapper.addUser(new User(2, "user", "1024", 20, "女")); //更新用户操作 userMapper.updateUser(new User(1,"newName","000000",24,"男")); //根据 uid 删除用户操作 userMapper.deleteUser(2) //计数 System.out.println(userMapper.getCount()); //返回值为 List 的全体查询 List allUserList = userMapper.getAllUser(); for(User user : AllUserList) { System.out.println(user); } //返回值为 Map 的全体查询 Map allUserMap = userMapper.getAllUserMap(); User u1 = (User) map.get(1); System.out.println(u); //返回值为 Map 的按 uid 查询 Map userMap = userMapper.getUserMapByUid("1"); User u2 = (User) map.get(1); System.out.println(u); //提交事务 sqlSession.conmmit(); } }

注意

本例中对于 UserMapper.xml 中的 resultType 与 Mapper 接口中方法返回值并不完全一致。

UserMapper 接口中 getAllUser() 返回值为 List 但 UserMapper.xml 中对应的语句 resultType 为 User.

MyBatis 在处理 List 集合返回值时会进行自动类型转换,仅需指定集合的泛型类型即可。

UserMapper 接口中 getAllUserMap 和 getUserMapByid方法返回值均为 Map,但在 UserMapper.xml 中对应的 resultType 为 User

MyBatis 在处理 Map 集合时也会进行自动类型转换,而键的值取决于 UserMapper 接口中对应方法的注解 @MapKey()。本例中设计为@MapKey("uid"),因此 Map 的键值类型为 uid 字段的类型,通过该 Map 取值时也是根据 uid 的值为键从中取值。

再次提醒本例没有像上一章例中采用自动事务提交,而是使用手动事物提交,当然读者也可以将其设为自动提交,自动提交无需最后一句 sqlsession.conmmit() 进行事务提交。

六. MyBatis 获取参数的两种方式

MyBatis 由 JDBC 中来设定了两种传参的方法,一种是使用通配符的传参方式,一种是参数拼接的传参方式。

通配符式的传参方式 #{}

在 JDBC 中使用 PreparedStatement 式的 SQL 执行,可以使用通配符

insert into user value(null,?,?,?,?)

该种方式传参还可以防止 SQL 注入

该方式的传参与顺序有关,与参数名称无关

但传输的对象为 Java 对象时通过属性名直接或得属性值

参数拼接的传参方式 ${}

在 JDBC 中使用 statement 式的 SQL 执行,使用字符串拼接的方式操作 SQL

insert into user value(null,"admin","123456",23,"男")

需要注意字符串参数的单引号问题

该方式的传参需要与参数名称(字段名)一致

当多参数传参时,MyBatis 会默认将这些参数放在 map 集合中

键为 0,1,2,3 … N-1,以参数为值

#{0},#{1},#{3}

键为 param1,param2,param3 … paramN,以参数为值

#{param1},#{param2},#{param3}

p a r a m 1 , {param1}, param1,{param2},${param3}

自定义 map 集合,进行传参

Mybatis 可以将参数放到 map 集合中,那么也可以自定义将参数放到 map 集合中

在映射接口中添加方法

user getUserByMap(Map map);

在 UserMapper.xml 映射文件中添加

select * from user where uid = ${uid_} and password = '${password_}'

测试

Map map = new HashMap(); //此处使用 uid_ 与 password_ 为键放入值是根据上面在 UserMapper.xml 的定义 map.put("uid_","1"); map.put("password_","123456"); //将 map 集合参数传入 User user = mapper.getUserByMap(map);

使用 @Param() 注解(命名参数)

在映射接口的方法参数中使用注释 @Param() 直接定义其传参键名

user getUserByMap(@Param("uid_")String uid,@Param("password_")String password);

之后传参时直接可以使用其注释中的名称作为键名

七. 获取自动生成的主键

若在数据库表中插入一个对象,此时其自动生成了主键,如何获取该自动生成的主键呢

Mapper 文件

insert into user values(null,#{uid},#{password},#{age},#{sex})

此时在测试类中可以获得自动生成的主键

UserMapper userMapper = new sqlSession.getMapper(UserMapper.class); User user = new User(null,"new admin","123456",24,"男"); userMapper.insertUser(user); //key此时将变为主键 int key = user.getUid(); 相关链接

MyBatis 文档:https://mybatis.org/mybatis-3/zh/index.html

文章内容来自个人学习总结 欢迎指出本文中存在的问题 未经本人同意禁止转载,不得用于商业用途


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3