在上一篇文章中我们介绍了如何使用JDBC实现一个简单的表格查询功能,今天,我们将使用Mybatis实现同样的功能,通过对比这两次不同的实现我们可以明确感受到JDBC和Mybatis的不同。此外,在本文还将简单介绍Mybatis的简单增删改查操作方法,包括基于xml文件和基于注解两种方式。文中的很多内容都能在一定程度上让我们的开发之旅更加轻松方便,这是一个菜鸟提升技术能力,老鸟巩固基础知识的好机会。准备好开启今天的神奇之旅了吗?
大家好,我是奇迹老李,一个专注于分享开发经验和基础教程的博主。这里是我的其中一个技术分享平台,欢迎广大朋友们点赞评论提出意见,重要的是点击关注喔 🙆。今天要和大家分享的内容是Mybatis的快速入门。做好准备,Let’s go🚎🚀
还是这个简单的查询功能,在上一篇文章中我们通过JDBC实现了这个查询,今天我们通过Mybatis来实现相同的功能,包括如下几个步骤:
一个简单的Mybatis配置文件内容如下代码所示。其中各个配置项的实际意义我们将在后续的文章中陆续解释,这里直接复制代码即可
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--外部资源-->
<properties resource="mysql-env.properties"/>
<!--配置数据源-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--配置映射文件位置-->
<mappers>
<mapper resource="mapper/ApplicationMapper.xml"/>
</mappers>
</configuration>
package top.sunyog.mybatis;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import top.sunyog.common.entity.AppSearchVo;
import top.sunyog.common.entity.AppTestEntity;
import top.sunyog.mybatis.mapper.ApplicationRepository;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisApp {
public static void main(String[] args) {
try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml")) {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
...
} catch (IOException e) {
System.out.println("资源路径错误");
}
}
}
包括接口和xml文件,mapper接口如下:
package top.sunyog.mybatis.mapper;
import top.sunyog.common.entity.AppSearchVo;
import top.sunyog.common.entity.AppTestEntity;
import java.util.List;
public interface ApplicationRepository {
List<AppTestEntity> queryApp(AppSearchVo param);
}
mapper映射xml文件如下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.sunyog.mybatis.mapper.ApplicationRepository">
...
<select id="queryApp" resultType="top.sunyog.common.entity.AppTestEntity">
select id,app_name,app_code,auth_type,create_date,creator from app_test
<where>
<if test="null != appName and ''.toString() != appName">and app_name like concat('%',#{appName},'%')</if>
<if test="null != authType and ''.toString() != authType">and auth_type = #{authType}</if>
<if test="null != startDate and '' != startDate">and create_date >= #{startDate}</if>
<if test="null != endDate and '' != endDate">and create_date <= #{endDate}</if>
</where>
</select>
</mapper>
AppTestEntity类的具体代码如下
public class AppTestEntity {
private Long id;
private String appName;
private String appCode;
private String authType;
private LocalDate createDate;
private String creator;
private String appStatus;
//省略getter、setter、to'S方法
}
...
public class MybatisApp {
public static void main(String[] args) {
try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml")) {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
AppSearchVo param = new AppSearchVo();
param.setAppName("应用");
param.setAuthType("2");
SqlSession session = sqlSessionFactory.openSession();
ApplicationRepository mapper = session.getMapper(ApplicationRepository.class);
List<AppTestEntity> list = mapper.queryApp(param);
list.forEach(o-> System.out.println(o));
session.close();
} catch (IOException e) {
System.out.println("资源路径错误");
}
}
}
按照以上步骤执行后,会发现打印出的结果都是空数据,这是由于数据库中app_test表的字段名和AppTestEntity
类的属性名不一致,没有映射成功导致的,解决这个问题有两种方式
结果映射的方式有两种可以通过ResultMap标签直接编辑,也可以通过配置Mybatis的自动映射实现该功能
通过ResultMap
映射
<mapper namespace="...">
<resultMap id="appTestMap" type="top.sunyog.common.entity.AppTestEntity">
<result column="app_name" property="appName"/>
<result column="app_code" property="appCode"/>
<result column="auth_type" property="authType"/>
<result column="create_date" property="createDate"/>
</resultMap>
<select id="queryApp" resultMap="appTestMap">...</select>
</mapper>
在配置文件中配置mapUnderscoreToCamelCase
为true
,使用这种方式需要保证数据库中的字段下划线命名和java类中的驼峰命名一一对应
<configuration>
<properties .../>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<environments .../>
<mappers>
...
</mappers>
</configuration>
配置文件中的 mysql-env.properties
文件内容为
driver=com.mysql.cj.jdbc.Driver
#需替换为自己数据库url
url=jdbc:mysql://localhost:3306/sunyog_db?serverTimezone=Asia/Shanghai
username=你自己的用户名
password=你自己的没密码
项目的具体目录结构如下
mybatis-demo
|-src
|-main
|-java
|-top
|-sunyog
|-common
|-entity
|-AppTestEntity.java
|-mybatis
|-mapper
|-ApplicationRepository.java
|-MybatisApp.java
|-resources
|-mapper
|-ApplicationMapper.xml
|-mysql-env.properties
|-mybatis-config.xml
|-test
|-java
|-resources
在mybatis的mapper文件中,以下标签分别对应数据库的增、删、改、查操作
<insert id="" parameterType=""></insert>
<delete id=""></delete>
<update id="" parameterType=""></update>
<select id="" resultType=""></select>
为了方便测试,我们对之前的main方法进行改造,改造后的效果如下
public class MybatisApp {
public static void main(String[] args) {
SqlSession session=null;
try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml")) {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(in);
session = sqlSessionFactory.openSession();
ApplicationRepository mapper = session.getMapper(ApplicationRepository.class);
// testInsert(mapper);
testDelete(mapper);
// testUpdate(mapper);
// testQuery(mapper);
session.commit();
} catch (IOException e) {
System.out.println("资源路径错误");
} finally {
if (session!=null){
session.close();
}
}
}
}
//mapper接口
int addApp(AppTestEntity entity);
<mapper>
<insert id="addApp" parameterType="top.sunyog.common.entity.AppTestEntity">
insert into app_test(app_name,app_code,auth_type,create_date,creator)
values(#{appName},#{appCode},#{authType},#{createDate},#{creator})
</insert>
</mapper>
//测试代码
private static void testInsert(ApplicationRepository mapper) {
AppTestEntity entity = new AppTestEntity();
entity.setAppName("测试新增");
entity.setAppCode("test_add_app");
entity.setAuthType("2");
entity.setCreateDate(LocalDate.now());
entity.setCreator("admin2");
int row = mapper.addApp(entity);
System.out.println("新增成功, 影响行数: "+row);
}
以下代码具有和xml映射文件同等的作用
@Insert("insert into app_test(app_name,app_code,auth_type,create_date,creator)"+
"values(#{appName},#{appCode},#{authType},#{createDate},#{creator})")
int addApp(AppTestEntity entity);
int deleteById(Long id);
<mapper>
<delete id="deleteById" parameterType="long">
delete from app_test where id=#{id}
</delete>
</mapper>
private static void testDelete(ApplicationRepository mapper) {
int row = mapper.deleteById(4L);
System.out.println("删除成功,影响行数: "+row);
}
以下代码具有同等作用
@Delete("delete from app_test where id=#{id}")
int deleteById(Long id);
int updateById(AppTestEntity entity);
<mapper>
<update id="updateById" parameterType="top.sunyog.common.entity.AppTestEntity">
<!-- update app_test set app_name=#{appName},app_code=#{appCode},auth_type=#{authType},create_date=#{createDate},-->
<!-- creator=#{creator} where id=#{id}-->
update app_test
<set>
<if test="appName != null and '' != appName">app_name = #{appName},</if>
<if test="appCode != null and '' != appCode">app_code = #{appCode},</if>
<if test="authType != null and '' != authType">auth_type = #{authType},</if>
<if test="createDate != null and '' != createDate">create_date = #{createDate},</if>
<if test="creator != null and '' != creator">creator = #{creator},</if>
</set>
where id=#{id}
</update>
</mapper>
private static void testUpdate(ApplicationRepository mapper) {
AppTestEntity entity = new AppTestEntity();
// entity.setAppName("测试修改3");
entity.setId(4L);
// entity.setAppCode("test_update_app");
entity.setAuthType("2");
// entity.setCreateDate(LocalDate.now());
// entity.setCreator("zhangsan");
int row = mapper.updateById(entity);
System.out.println("修改成功,影响行数: "+row);
}
更新操作中存在动态sql标签,直接使用 @Update
注解会使代码变复杂,后续动态sql章节详细介绍基于注解的写法。
通过ID查询
AppTestEntity queryById(Long id);
<mapper>
<select id="queryById" resultType="top.sunyog.common.entity.AppTestEntity">
select id,app_name,app_code,auth_type,create_date,creator from app_test where id=#{id} limit 0,1
</select>
</mapper>
private static void testOne(ApplicationRepository mapper) {
AppTestEntity entity = mapper.queryById(1L);
System.out.println(entity);
}
以下代码具有同等作用
@Select("select id,app_name,app_code,auth_type,create_date,creator from app_test where id=#{id} limit 0,1")
AppTestEntity queryById(Long id);
通过条件查询列表
List<AppTestEntity> queryApps(Map map);
<select id="queryApp" resultType="top.sunyog.common.entity.AppTestEntity">
select id, app_name, app_code, auth_type, create_date, creator from app_test
<where>
<if test="null != appName and ''.toString() != appName">and app_name like concat('% ',#{appName},' %')</if>
<if test="null != authType and ''.toString() != authType">and auth_type = #{authType}</if>
<if test="null != startDate and '' != startDate">and create_date >= #{startDate}</if>
<if test="null != endDate and '' != endDate">and create_date <= #{endDate}</if>
</where>
</select>
private static void testList(ApplicationRepository mapper) {
Map<String,Object> map=new HashMap(8);
map.put("appName","测试");
map.put("endDate",new Date());
List<AppTestEntity> entitys = mapper.queryApps(1L);
System.out.println(entitys);
}
以上代码存在的问题
xml标签中parameterType
和parameterType
元素写类全名过长
列表查询和单个查询中存在重复代码
删除功能在业务上一般都是逻辑删除
insert语句新增的不一定是单行数据,可能是一个数组或list列表
这些问题我们将在后续的文章中进行一一分析
在这篇文章中,我们介绍了mybatis的最基础用法,同时实现了一个简单的表格查询功能,通过对比JDBC的实现和Mybatis的实现我们可以看出,相比与JDBC,使用Mybatis框架进行开发具有很多优点
mapUnderscoreToCamelCase
配置项📩 联系方式
邮箱:qijilaoli@foxmail.com?版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问奇迹老李的博客首页