百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

MyBatis学习笔记(二)(mybatis入门菜鸟教程)

mhr18 2024-10-17 10:35 18 浏览 0 评论

接上期《MyBatis学习笔记(一)》

3.7 添加用户

3.7.1 映射文件:

<!-- 添加用户

parameterType:指定输入 参数类型是pojo(包括 用户信息)

#{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值

-->

<insert id="insertUser" parameterType="org.hxweb.web.ssm.pojo.User">

<!--

将插入数据的主键返回,返回到user对象中


SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键


keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性

order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序

resultType:指定SELECT LAST_INSERT_ID()的结果类型

-->

<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">

SELECT LAST_INSERT_ID()

</selectKey>

insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})

<!--

使用mysql的uuid()生成主键

执行过程:

首先通过uuid()得到主键,将主键设置到user对象的id属性中

其次在insert执行时,从user对象中取出id属性值

-->

<!-- <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">

SELECT uuid()

</selectKey>

insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address}) -->

</insert>

3.7.2 程序代码:

// 添加用户信息

@Test

public void insertUserTest() throws IOException {

// mybatis配置文件

String resource = "config/SqlMapConfig.xml";

// 得到配置文件流

InputStream inputStream = Resources.getResourceAsStream(resource);

// 创建会话工厂,传入mybatis的配置文件信息

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()

.build(inputStream);

// 通过工厂得到SqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();

// 插入用户对象

User user = new User();

user.setUsername("王小军");

user.setBirthday(new Date());

user.setSex("1");

user.setAddress("河南郑州");

sqlSession.insert("test.insertUser", user);

// 提交事务

sqlSession.commit();

// 获取用户信息主键

System.out.println(user.getId());

// 关闭会话

sqlSession.close();

}

3.7.3 自增主键的返回

mysql的自增注解,是在执行insert提交之前自动生成一个自增主键。

通过mysql的函数获去到刚刚插入记录的自增主键:

SELECT MYSQL_INSERT_ID()

是insert之后调用此函数。

需要修改insertUser的 mappedstatement 定义

<!--

将插入数据的主键返回,返回到user对象中


SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键


keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性

order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序

resultType:指定SELECT LAST_INSERT_ID()的结果类型

<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">

SELECT LAST_INSERT_ID()

</selectKey>

-->

insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})

3.7.4 非自增主键返回

使用 mysql的uuid()函数

id类型修改为varchar(35)

先通过uuid()函数查询到主键,将主键输入到sql语句

SELECT uuid()

执行uuid()的顺序相对于insert执行之前执行。

<!--

使用mysql的uuid()生成主键

执行过程:

首先通过uuid()得到主键,将主键设置到user对象的id属性中

其次在insert执行时,从user对象中取出id属性值

-->

<!-- <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">

SELECT uuid()

</selectKey>

insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})

-->

ORACLE 通过序列生产主键

<!--

使用oracle的seq生成主键

执行过程:

首先通过seq得到主键,将主键设置到user对象的id属性中

其次在insert执行时,从user对象中取出id属性值

-->

<!-- <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">

select seq.nextval from dual

</selectKey>

insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})

-->

3.8 根据id删除用户信息

3.8.1 映射文件

<!-- 删除 用户

根据id删除用户,需要输入 id值

-->

<delete id="deleteUser" parameterType="java.lang.Integer">

delete from user where id=#{id}

</delete>

3.8.2 程序代码

// 根据id删除 用户信息

@Test

public void deleteUserTest() throws IOException {

// mybatis配置文件

String resource = "config/SqlMapConfig.xml";

// 得到配置文件流

InputStream inputStream = Resources.getResourceAsStream(resource);

// 创建会话工厂,传入mybatis的配置文件信息

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()

.build(inputStream);

// 通过工厂得到SqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();

// 传入id删除 用户

sqlSession.delete("test.deleteUser", 39);

// 提交事务

sqlSession.commit();

// 关闭会话

sqlSession.close();

}

3.9 根据id更新用户

3.9.1 映射文件

<!-- 根据id更新用户

分析:

需要传入用户的id

需要传入用户的更新信息

parameterType指定user对象,包括 id和更新信息,注意:id必须存在

#{id}:从输入 user对象中获取id属性值

-->

<update id="updateUser" parameterType="org.hxweb.web.ssm.pojo.User">

update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}

where id=#{id}

</update>

3.9.2 程序代码

// 更新用户信息

@Test

public void updateUserTest() throws IOException {

// mybatis配置文件

String resource = "config/SqlMapConfig.xml";

// 得到配置文件流

InputStream inputStream = Resources.getResourceAsStream(resource);

// 创建会话工厂,传入mybatis的配置文件信息

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()

.build(inputStream);

// 通过工厂得到SqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();

// 更新用户信息

User user = new User();

//必须设置id

user.setId(41);

user.setUsername("王大军");

user.setBirthday(new Date());

user.setSex("2");

user.setAddress("河南郑州");

sqlSession.update("test.updateUser", user);

// 提交事务

sqlSession.commit();

// 关闭会话

sqlSession.close();

}

3.10 总结

3.10.1 parameterType

在映射文件中通过parameterType指定输入 参数类型

3.10.2 resultType

在映射文件中通过resultType指定数据结果的类型

3.10.3 #{} 和 ${}

#{}:表示一个占位符号

1)#{}接收输入参数,类型可以是简单类型、pojo、hashmap:

2)#{}接收简单类型参数:#{}中可以是value或者其它名称。

3)#{}接收pojo对象,通过OGNL对象导航图读取pojo对象中的属性值通过属性.属性.属性...方式获取对象属性值。

4)${}:表示一个拼接符号,会引起sql注入,存在安全隐患,不建议使用${}。

${}接收输入参数,类型可以是简单类型、pojo、hashmap:

1)${}简单类型参数:${}中只可以写成value。

2)${}接收pojo对象,通过OGNL对象导航图读取pojo对象中的属性值通过属性.属性.属性...方式获取对象属性值。

3.10.4 selectOne 和 selectList

1.selectOne表示查询出一条记录进行映射。如果使用 selectOne 能够实现使用 selectList 也可以实现(list中只有一个对象)

2.selectList表示查出一个列表(多条记录)进行映射。如果使用 selectList 查询多条记录不能使用 selectOne

如果使用 selectOne 会报错:

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3

3.但 如果 selectList查询一条记录,selectOne 也可以实现。

3.11 mybatis与hibernate的本质区别和应用场景

3.11.1 hibernate

本质区别:是一个标准的ORM框架(对象关系映射),入门门槛较高,不需要程序员编写sql,自动生成sql语句。

对sql语句的修改、优化比较困难。

应用场景:适用于需求变化不多的中小型项目,比如:后台管理系统,erp、crm、oa。

3.11.2 mybatis

本质区别:专注sql,需要程序员自己编写sql,sql的修改、优化比较方便。

mybatis 是一个不完全的 ORM框架,mybatis也可以实现映射(输入映射、输出映射)。

应用场景:适用于需求变化较多的项目,比如:互联网项目。

3.11.3 企业技术选项,要以低成本,高回报作为技术选择的原则,根据项目组的技术力量继续抉择。

4.mybatis 开发 dao 的方法

4.1 SqlSession 的使用范围

4.1.1 SqlSessionFactoryBuilder

通过 SqlSessionFactoryBuilder 创建会话工厂 SqlSessionFactory

将 SqlSessionFactoryBuilder 当做一个工具类使用即可,不需要使用单例来管理 SqlSessionFactoryBuilder 。

当需要创建 SqlSessionFactory 时,只需new一次 SqlSessionFactoryBuilder 即可。

4.1.2 SqlSessionFactory

通过 SqlSessionFactory 创建会话 SqlSession ,使用单例模式管理 SqlSessionFactory (工厂一创建,一直使用一个实例)

将来 mybatis 和 spring 整合 springIOC 使用单例模式管理 SqlSessionFactory

4.1.3 SqlSession

SqlSession 是面向用户(程序员)的接口。

SqlSession 中提供了很多操作数据库的方法:如 selectOne(返回单个对象) 和 selsectList (返回单个或多个对象)

SqlSession 是线程不安全的,在 SqlSession 实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。

SqlSession 的最佳应用场合在方法体内,定义成局部变量使用。

4.2 原始 dao 的开发方法(程序员需要编写 dao接口和 dao 实现类)

4.2.1 思路:

1)程序员需要编写 dao 接口和 dao 接口实现类

2)需要向 dao 接口实现类中注入 SqlSessionFactory,在方法体内通过 SqlSessionFactory 创建 SqlSession。

4.2.2 dao 接口

import org.hxweb.web.ssm.pojo.User;

/**

* @see 用户管理dao 接口

* @author Administrator

*

*/

public interface UserDao {

//根据id查询用户信息

public User findUserById(Integer id) throws Exception;

//添加用户

public void insertUser(User user) throws Exception;

//根据id删除用户

public void deleteUserById(Integer id) throws Exception;

}

4.2.3 dao 接口实现类

package org.hxweb.web.ssm.dao.impl;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.hxweb.web.ssm.dao.UserDao;

import org.hxweb.web.ssm.pojo.User;

/**

* @see dao 实现类

* @author Administrator

*

*/

public class UserDaoImpl implements UserDao {

// 要向 dao 接口实现类中注入 SqlSessionFactory,在方法体内通过 SqlSessionFactory 创建 SqlSession

// 这里通过构造函数注入 SqlSessionFactory

private SqlSessionFactory sqlSessionFactory;

public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {

this.sqlSessionFactory = sqlSessionFactory;

}

@Override

public User findUserById(Integer id) throws Exception {

// 通过工厂得到SqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();

// 通过SqlSession操作数据库

// 第一个参数:映射文件中statement的id,等于=namespace+"."+statement的id

// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数

// sqlSession.selectOne结果 是与映射文件中所匹配的resultType类型的对象

// selectOne查询出一条记录

User user = sqlSession.selectOne("test.findUserById", id);

// 释放资源

sqlSession.close();

return user;

}

@Override

public void insertUser(User user) throws Exception {

// 通过工厂得到SqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();

// 执行插入的操作

sqlSession.insert("test.insertUser", user);

// 提交事务

sqlSession.commit();

// 获取用户信息主键

System.out.println(user.getId());

// 关闭会话

sqlSession.close();

}

@Override

public void deleteUserById(Integer id) throws Exception {

// 通过工厂得到SqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();

// 传入id删除 用户

sqlSession.delete("test.deleteUser", id);

// 提交事务

sqlSession.commit();

// 关闭会话

sqlSession.close();

}

}

4.2.3 单元测试类

package org.hxweb.web.ssm.test;

import static org.junit.Assert.*;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.hxweb.web.ssm.dao.UserDao;

import org.hxweb.web.ssm.dao.impl.UserDaoImpl;

import org.hxweb.web.ssm.pojo.User;

import org.junit.Before;

import org.junit.Test;

public class UserDaoImplTest {

private SqlSessionFactory sqlSessionFactory;

@Before

public void setUp() throws Exception {

// 创建SqlSessionFactory

String resource = "config/SqlMapConfig.xml";

// 得到配置文件流

InputStream inputStream = Resources.getResourceAsStream(resource);

// 创建会话工厂,传入mybatis的配置文件信息

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

}

@Test

public void testFindUserById() throws Exception {

// 创建UserDao对象

UserDao userDao = new UserDaoImpl(sqlSessionFactory);

// 调用UserDao对象

User user = userDao.findUserById(1);

// 输出对象

System.out.println(user);

}

}

4.2.5 总结原始 dao 开发方法问题

1.dao接口实现类方法中存在大量的模板方法,设想能否将模板方法提取处理,大大减轻程序员的工作量。

2.在调用 session 方法时将 statement 的id硬编码了。

3.在调用 session 方法时传入的变量,由于 session 方法使用泛型,即使传入变量类型错误,在编译阶段也不会报错,不利于程序员开发。

4.3 mapper代理方法(程序员只需要开发mapper接口(相当于dao接口))

4.3.1 思路(开发规范):

4.3.1.1 程序员需编写mapper接口对应的mapper.xml(映射文件)

4.3.1.2 程序员只需要编写mapper接口(相当于dao接口)只要遵循以下开发规范,mybatis可以自动生成mapper接口实现类代理对象。

需要遵循的一些开发规范:

1.在mapper.xml 中 namespace 等于 mapper接口地址(全类名)

<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离

注意:使用mapper代理方法开发,namespace有特殊重要的作用,namespace 等于 mapper 接口地址(全类名)

-->

<mapper namespace="org.hxweb.web.ssm.mapper.UserMapper">

2.mapper.java 接口中的方法名与 mapper.xml 中 statement 的id一致。

3.mapper.jave 接口中的方法输入参数的类型与 mapper.xml 中 statement 的 parameterType 指定的类型一致。

4.mapper.jave 接口中的方法返回值的类型与 mapper.xml 中 statement 的 resultType 指定的类型一致。

<select id="findUserById" parameterType="java.lang.Integer" resultType="org.hxweb.web.ssm.pojo.User">

SELECT * FROM user WHERE id=#{value}

</select>

// 根据id查询用户信息

public User findUserById(Integer id) throws Exception;

4.3.1.3 总结,以上开发规范主要对下边之类的代码进行统一生成:

User user = sqlSession.selectOne("test.findUserById", id);

4.3.2 mapper.java

//根据id查询用户信息

public User findUserById(Integer id) throws Exception;

4.3.3 mapper.xml

<select id="findUserById" parameterType="java.lang.Integer" resultType="org.hxweb.web.ssm.pojo.User">

SELECT * FROM user WHERE id=#{value}

</select>

4.3.4 在SqlMapConfig.xml加载映射文件

在sqlMapConfig.xml中加载 UserMapper.xml:

<!-- 加载 映射文件 -->

<!-- 加载 映射文件 -->

<mappers>

<mapper resource="config/sqlmap/User.xml"/>

<mapper resource="config/mapper/UserMapper.xml"/>

</mappers>

4.3.5 测试类代码

package org.hxweb.web.ssm.test;

import static org.junit.Assert.*;

import java.io.InputStream;

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.hxweb.web.ssm.mapper.UserMapper;

import org.hxweb.web.ssm.pojo.User;

import org.junit.Before;

import org.junit.Test;

public class UserMapperTest {

private SqlSessionFactory sqlSessionFactory;

@Before

public void setUp() throws Exception {

// 创建SqlSessionFactory

String resource = "config/SqlMapConfig.xml";

// 得到配置文件流

InputStream inputStream = Resources.getResourceAsStream(resource);

// 创建会话工厂,传入mybatis的配置文件信息

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

}

@Test

public void testFindUserById() throws Exception {

SqlSession sqlSession = sqlSessionFactory.openSession();

//创建UserMapper对象,mybatis自动生成mapper代理对象

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

//调用userMapper的方法

User user = userMapper.findUserById(1);

System.out.println(user);

}

}

4.3.6 问题总结

4.3.6.1 代理对象内部调用 selectOne 或 selectList

如果 mapper 方法返回单个pojo对象(非集合对象),代理对象内部通过 selectOne 查询数据库。

如果 mapper 方法返回集合对象,代理对象内部通过 selectList 查询数据库。

4.3.6.2 mapper 接口方法的参数只能有一个是否影响我们的系统编码

mapper 接口方法中只有一个参数,是否不利于系统的扩展维护。

系统框架中 dao接口是被 业务层(service)公用的。

即使mapper 接口方法中只有一个参数,可以利用包装类型的 pojo 满足不同的业务方法的需求。

注意:持久层方法的参数可以使用包装类型 pojo、map、...,service层方法中建议不要使用包装类型 pojo(不利于业务层的扩展)。

相关推荐

【预警通报】关于WebLogic存在远程代码执行高危漏洞的预警通报

近日,Oracle官方发布了2021年1月关键补丁更新公告CPU(CriticalPatchUpdate),共修复了包括CVE-2021-2109(WeblogicServer远程代码执行漏洞)...

医院信息系统突发应急演练记录(医院信息化应急演练)

信息系统突发事件应急预案演练记录演练内容信息系统突发事件应急预案演练参与人员信息科参与科室:全院各部门日期xxxx-xx-xx时间20:00至24:00地点信息科记录:xxx1、...

一文掌握怎么利用Shell+Python实现完美版的多数据源备份程序

简介:在当今数字化时代,无论是企业还是个人,数据的安全性和业务的连续性都是至关重要的。数据一旦丢失,可能会造成无法估量的损失。因此,如何有效地对分布在不同位置的数据进行备份,尤其是异地备份,成为了一个...

docker搭建系统环境(docker搭建centos)

Docker安装(CentOS7)1.卸载旧版Docker#检查已安装版本yumlistinstalled|grepdocker#卸载旧版本yumremove-ydocker.x...

基础篇:数据库 SQL 入门教程(sql数据库入门书籍推荐)

SQL介绍什么是SQLSQL指结构化查询语言,是用于访问和处理数据库的标准的计算机语言。它使我们有能力访问数据库,可与多种数据库程序协同工作,如MSAccess、DB2、Informix、M...

Java21杀手级新特性!3行代码性能翻倍

导语某券商系统用这招,交易延迟从12ms降到0.8ms!本文揭秘Oracle官方未公开的Record模式匹配+虚拟线程深度优化+向量API神操作,代码量直降70%!一、Record模式匹配(代码量↓8...

一文读懂JDK21的虚拟线程(java虚拟线程)

概述JDK21已于2023年9月19日发布,作为Oracle标准Java实现的一个LTS版本发布,发布了15想新特性,其中虚拟线程呼声较高。虚拟线程是JDK21中引入的一项重要特性,它是一种轻量级的...

效率!MacOS下超级好用的Linux虚拟工具:Lima

对于MacOS用户来说,搭建Linux虚拟环境一直是件让人头疼的事。无论是VirtualBox还是商业的VMware,都显得过于笨重且配置复杂。今天,我们要介绍一个轻巧方便的纯命令行Linux虚拟工具...

所谓SaaS(所谓三维目标一般都应包括)

2010年前后,一个科技媒体的主编写一些关于云计算的概念性问题,就可以作为头版头条了。那时候的云计算,更多的还停留在一些概念性的问题上。而基于云计算而生的SaaS更是“养在深闺人未识”,一度成为被IT...

ORA-00600 「25027」 「x」报错(报错0xc0000001)

问题现象:在用到LOB大对象的业务中,进行数据的插入,失败了,在报警文件中报错:ORA-00600:内部错误代码,参数:[25027],[10],[0],[],[],[],[],[...

安卓7源码编译(安卓源码编译环境lunch失败,uname命令找不到)

前面已经下载好源码了,接下来是下载手机对应的二进制驱动执行编译源码命令下载厂商驱动https://developers.google.com/android/drivers?hl=zh-cn搜索NGI...

编译安卓源码(编译安卓源码 电脑配置)

前面已经下载好源码了,接下来是下载手机对应的二进制驱动执行编译源码命令下载厂商驱动https://developers.google.com/android/drivers?hl=zh-cn搜索NGI...

360 Vulcan Team首战告捷 以17.5万美金强势领跑2019“天府杯“

2019年11月16日,由360集团、百度、腾讯、阿里巴巴、清华大学与中科院等多家企业和研究机构在成都联合主办了2019“天府杯”国际网络安全大赛暨2019天府国际网络安全高峰论坛。而开幕当日最激荡人...

Syslog 日志分析与异常检测技巧(syslog发送日志配置)

系统日志包含有助于分析网络设备整体运行状况的重要信息。然而,理解并从中提取有效数据往往颇具挑战。本文将详解从基础命令行工具到专业日志管理软件的全流程分析技巧,助你高效挖掘Syslog日志价值。Gr...

从Oracle演进看数据库技术的发展(从oracle演进看数据库技术的发展的过程)

数据库技术发展本质上是应用需求驱动与基础架构演进的双向奔赴,如何分析其技术发展的脉络和方向?考虑到oracle数据库仍然是这个领域的王者,以其为例,管中窥豹,对其从Oracle8i到23ai版本的核...

取消回复欢迎 发表评论: