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

Mybatis_day01(Java真正的全栈开发)

mhr18 2024-10-13 03:30 25 浏览 0 评论

更多资源分享就在【Java帮帮】微信公众号与QQ空间

Mybatis_day01

前言

Jdbc演变到mybatis

jdbc

jdbc编程

publicstaticvoid main(String[] args) {

Connection connection = null;

PreparedStatement preparedStatement = null;

ResultSet resultSet = null;

try {

//加载数据库驱动

Class.forName("com.mysql.jdbc.Driver");

//通过驱动管理类获取数据库链接

connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mysql");

//定义sql语句 ?表示占位符

String sql = "select * from user where username = ?";

//获取预处理statement

preparedStatement = connection.prepareStatement(sql);

//设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值

preparedStatement.setString(1, "王五");

//向数据库发出sql执行查询,查询出结果集

resultSet = preparedStatement.executeQuery();

//遍历查询结果集

while(resultSet.next()){

System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));

}

} catch (Exception e) {

e.printStackTrace();

}finally{

//释放资源

if(resultSet!=null){

try {

resultSet.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

if(preparedStatement!=null){

try {

preparedStatement.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

if(connection!=null){

try {

connection.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

上述jdbc查询未经封装,原生态的查询方式

jdbc编程步骤

1.加载数据库驱动

2.创建并获取数据源连接

3.创建jdbc的statement对象

4.设置sql语句

5.设置statement中的sql参数(statement的参数注入)

6.statement执行sql语句

7.对sql执行结果进行解析处理

8.释放资源(statement,connection,resultSet)

jdbc演变到mybatis

上面我们看到了实现JDBC有七个步骤,哪些步骤是可以进一步封装的,减少我们开发的代码量

第一步优化:连接获取和释放

问题描述:

数据库连接频繁的开启和关闭本身就造成了资源的浪费,影响系统的性能。

解决问题:

数据库连接的获取和关闭我们可以使用数据库连接池来解决资源浪费的问题。通过连接池就可以反复利用已经建立的连接去访问数据库了。减少连接的开启和关闭的时间。

问题描述:

但是现在连接池多种多样,可能存在变化,有可能采用DBCP的连接池,也有可能采用容器本身的JNDI数据库连接池。

解决问题:

我们可以通过DataSource进行隔离解耦,我们统一从DataSource里面获取数据库连接,DataSource具体由DBCP实现还是由容器的JNDI实现都可以,所以我们将DataSource的具体实现通过让用户配置来应对变化。

第二步优化:SQL统一存取

问题描述:

我们使用JDBC进行操作数据库时,SQL语句基本都散落在各个JAVA类中,这样有三个不足之处:

第一,可读性很差,不利于维护以及做性能调优。

第二,改动Java代码需要重新编译、打包部署。

第三,不利于取出SQL在数据库客户端执行(取出后还得删掉中间的Java代码,编写好的SQL语句写好后还得通过+号在Java进行拼凑)。

解决问题:

我们可以考虑不把SQL语句写到Java代码中,那么把SQL语句放到哪里呢?首先需要有一个统一存放的地方,我们可以将这些SQL语句统一集中放到配置文件或者数据库里面(以key-value的格式存放)。然后通过SQL语句的key值去获取对应的SQL语句。

既然我们将SQL语句都统一放在配置文件或者数据库中,那么这里就涉及一个SQL语句的加载问题。

第三步优化:传入参数映射和动态SQL

问题描述:

很多情况下,我们都可以通过在SQL语句中设置占位符来达到使用传入参数的目的,这种方式本身就有一定局限性,它是按照一定顺序传入参数的,要与占位符一一匹配。但是,如果我们传入的参数是不确定的(比如列表查询,根据用户填写的查询条件不同,传入查询的参数也是不同的,有时是一个参数、有时可能是三个参数),那么我们就得在后台代码中自己根据请求的传入参数去拼凑相应的SQL语句,这样的话还是避免不了在Java代码里面写SQL语句的命运。既然我们已经把SQL语句统一存放在配置文件或者数据库中了,怎么做到能够根据前台传入参数的不同,动态生成对应的SQL语句呢?

第四步优化:结果映射和结果缓存

问题描述:

执行SQL语句、获取执行结果、对执行结果进行转换处理、释放相关资源是一整套下来的。假如是执行查询语句,那么执行SQL语句后,返回的是一个ResultSet结果集,这个时候我们就需要将ResultSet对象的数据取出来,不然等到释放资源时就取不到这些结果信息了。我们从前面的优化来看,以及将获取连接、设置传入参数、执行SQL语句、释放资源这些都封装起来了,只剩下结果处理这块还没有进行封装,如果能封装起来,每个数据库操作都不用自己写那么一大堆Java代码,直接调用一个封装的方法就可以搞定了。

解决问题:

我们分析一下,一般对执行结果的有哪些处理,有可能将结果不做任何处理就直接返回,也有可能将结果转换成一个JavaBean对象返回、一个Map返回、一个List返回等等,结果处理可能是多种多样的。从这里看,我们必须告诉SQL处理器两点:第一,需要返回什么类型的对象;第二,需要返回的对象的数据结构怎么跟执行的结果映射,这样才能将具体的值copy到对应的数据结构上。

接下来,我们可以进而考虑对SQL执行结果的缓存来提升性能。缓存数据都是key-value的格式,那么这个key怎么来呢?怎么保证唯一呢?即使同一条SQL语句几次访问的过程中由于传入参数的不同,得到的执行SQL语句也是不同的。那么缓存起来的时候是多对。但是SQL语句和传入参数两部分合起来可以作为数据缓存的key值。

第五步优化:解决重复SQL语句问题

问题描述:

由于我们将所有SQL语句都放到配置文件中,这个时候会遇到一个SQL重复的问题,几个功能的SQL语句其实都差不多,有些可能是SELECT后面那段不同、有些可能是WHERE语句不同。有时候表结构改了,那么我们就需要改多个地方,不利于维护。

解决问题:

当我们的代码程序出现重复代码时怎么办?将重复的代码抽离出来成为独立的一个类,然后在各个需要使用的地方进行引用。对于SQL重复的问题,我们也可以采用这种方式,通过将SQL片段模块化,将重复的SQL片段独立成一个SQL块,然后在各个SQL语句引用重复的SQL块,这样需要修改时只需要修改一处即可。

优化总结:

我们总结一下上面对JDBC的优化和封装:

(1) 使用数据库连接池对连接进行管理

(2) SQL语句统一存放到配置文件

(3) SQL语句变量和传入参数的映射以及动态SQL

(4) 动态SQL语句的处理

(5) 对数据库操作结果的映射和结果缓存

(6) SQL语句的重复

一. Mybatis简介

1.什么是mybatis

myBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

Mybatis就是一个持久层的框架,是对jdbc的封装

2.mybatis架构设计

2.1.架构设计图



2.2.开发设计图

l mybatis配置

SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

l 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

l 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

l mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

l Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

l Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

l Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

二.mybatis入门

1.需求

根据用户ID(主键)进行查询用户信息

根据用户名称模糊查询用户信息

添加用户

删除用户

更新用户

2.环境

Java环境:jdk1.7.0_72

Eclipse:kepler

Mysql:5.5

mybaits的代码由github.com管理,地址:https://github.com/mybatis/mybatis-3/releases




mybatis-3.2.7.jar----mybatis的核心包

lib----mybatis的依赖包

mybatis-3.2.7.pdf----mybatis使用手册

3.创建mysql数据库

先导入sql_table.sql,再导入 sql_data.sql脚本:




如下:




4.mybatis入门程序

4.1.环境准备

4.1.1.创建一个Java工程




4.1.2.导入jar文件



4.1.3.log4j日志



4.1.4.创建sqlMapConfig.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>

<!-- 初始化环境,和spring整合以后,这个将会被废除 -->

<environments default="development">

<environment id="development">

<!-- 使用jdbc管理事务,事务控制是由mybatis来执行 -->

<transactionManager type="JDBC"/>

<!-- 数据源 也是由mybatis来进行管理-->

<dataSource type="POOLED">

<property name="driver" value="com.mysql.jdbc.Driver"/>

<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>

<property name="username" value="root"/>

<property name="password" value="admin"/>

</dataSource>

</environment>

</environments>

<mappers>

<!-- 引入映射文件 -->

<!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/> -->

</mappers>

</configuration>

sqlMapConfig是mybatis的核心配置文件,包含数据源,事务管理等等

4.1.5.创建PO类




4.2.根据ID查询用户

4.2.1.准备Mapper映射文件

在classpath下sqlMap里面创建映射文件User.xml(此名称可以任意定义)

但是:在mybatis代理开发时,必须命名XXXMapper.xml这样的样式

测试开发:使用普通模式进行开发、定义user.xml



User.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">

<!-- namespace是命名空间,用来隔离sql语句,可以随意定义,

注意:在使用代理时具有特殊的约定含义,不能随意定义 -->

<mapper namespace="test">

</mapper>

Namespace:命名空间 用来隔离sql语句,在mybatis代理模式具有特殊的含义

详细的mapper文件如下:

<?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是命名空间,用来隔离sql语句,可以随意定义,

注意:在使用代理时具有特殊的约定含义,不能随意定义 -->

<mapper namespace="test">

<!-- 首先明确:mybatis的所有sql语句都存放在xml的映射文件中,也就是说有多个sql -->

<!-- id:id就是我们唯一标识一个sql语句的地址

mybatis会将sql语句封装到mappedStatement对象中,id就是statement的id

注意:我们需要根据ID进行查询,需要接受参数使用parameterType进行接受参数

#,$都用来接受参数,就是占位符接受参数,注意:如果传递的是基本类型的参数,#{??}里面可以任意

parameterType:传递参数

resultType:结果集映射 -->

<select id="selectUserByID" parameterType="int" resultType="cn.itcast.bean.User">

select * from user where id=#{id}

</select>

</mapper>

4.2.2.ID查询测试类



测试代码:

publicclass MybatisTest {

private SqlSessionFactory sessionFactory;

@Before

publicvoid createSessionFactory() throws Exception{

String res="sqlMapConfig.xml";

InputStream inputStream = Resources.getResourceAsStream(res);

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

}

@Test

publicvoid test02(){

//获取Session

SqlSession session = sessionFactory.openSession();

User user = session.selectOne("test.selectUserByID", 1);

System.out.println(user);

session.close();

}

@Test

publicvoid test01() throws Exception{

String resources="sqlMapConfig.xml";

//读取文件资源流

InputStream inputStream = Resources.getResourceAsStream(resources);

//创建一个SessionFactory

SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//获取Session

SqlSession session = sessionFactory.openSession();

User user = session.selectOne("test.selectUserByID", 1);

System.out.println(user);

session.close();

}

}

4.3.根据姓名username模糊查询

4.3.1.映射文件

<!--需求:根据用户姓名进行模糊查询,可能返回多条记录

resultType:指定返回单条记录,映射成Java单个对象

${}拼接sql语句,对参数不加任何修饰的拼接在sql语句中

${value}:如果传入的参数类型是基本类型,那么${}内只能是value -->

<select id="selectUserByUsername" parameterType="string" resultType="cn.itcast.bean.User">

select * from user where username like '%${value}%'

</select>

4.3.2.测试代码模糊查询

@Test

publicvoid selectUserByUsername(){

SqlSession session = sessionFactory.openSession();

//第一个参数:statement的id,根据id找到需要执行的sql

//第二个参数:指定匹配parameterType的参数类型

List<User> list = session.selectList("test.selectUserByUsername", "张");

System.out.println(list);

}

4.4.#,$

#{}表示一个占位符,通过#{}可以实现preparedStatement向占位符中设置值,自动进行Java

类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接受简单类型值或pojo属性值。

如果parameterType传输单个类型的值,#{}括号中可以是value或者其他任意值。

${}表示拼接sql串,通过${}可以通过patameterType传入的内容拼接在sql中且不进行jdbc类型转换。${}可以接受简单类型值或pojo属性值,如果parameterType传输单个类型值,${}括号中只能是value.

4.5.parameterTyperesultType

patameterType:指定传递参数类型,mybatis通过ognl获取参数拼接在sql语句中

resultType:指定返回结果类型,mybatis可以把查询结果封装成Java对象,这里就是把结果集映射成resultType指定的对象。

4.6.selectOneselectList

selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:

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

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

selectList可以查询一条或多条记录。

5.添加

5.1.映射文件(user.xml)

<!-- parameterType:指定输入参数类型pojo,就是javabean对象

#{}口号中是Javabean的属性名,mybatis通过ognl来获取javabean的属性值 -->

<insert id="insertUser" parameterType="cn.itcast.bean.User">

<!--使用sql函数生成主键ID 注意:mysql主键是在执行完成insert语句后才增加主键,所以使用after -->

<selectKey keyProperty="id" order="AFTER" resultType="int">

SELECT LAST_INSERT_ID()

</selectKey>

insert into user(id,username,birthday,sex,address)

values(#{id},#{username},#{birthday},#{sex},#{address})

</insert>

Mysql自增主键返回:

selectKey实现自增主键返回:

keyProperty:返回值对应pojo里面的那个属性。

Order:表示id生成的顺序,由于mysql主键生成是在sql语句执行之后在进行设置,所以我们设置成after。

ResultType:主键返回类型

LAST_INSERT_ID()是mysql函数,返回auto_increament自增id值

也可以使用useGeneratedKeys来返回主键




5.2.添加测试代码

@Test

publicvoid test01() throws Exception{

SqlSession sqlSession = sessionFactory.openSession();

User user = new User();

user.setUsername("张三");

user.setSex("男");

user.setBirthday(new Date());

user.setAddress("陕西");

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

System.out.print(user.getId);//使用last_insert_Id返回ID

sqlSession.commit();

sqlSession.close();

}

5.3.mysql使用uuid实现主键自增



注意:mysql的uuid生成必须在执行insert之前进行,因为后面需要获取uuid的属性值进行表的插入。

5.4.oracle的自增序列

Oracle序列的自定义方法:



注意:oracle自增主键是序列化自增类型。需要before

6.删除

6.1.映射文件



6.2.删除测试

@Test

publicvoid deleteUserByID(){

SqlSession session = sessionFactory.openSession();

//删除单表,没有外键关联才能被删除

session.delete("test.deleteUserByID", 32);

session.commit();

session.close();

}

7.修改

7.1.映射文件



7.2.修改测试



7.3.测试结果



8.总结

8.1.parameterType

指定传递参数类型,前台传入参数和后台获取参数类型必须匹配

8.2.resultType

指定返回值类型,执行sql结果映射Java对象

8.3.#$

#{}表示一个占位符,#{}接受传入参数,类型可以是基本类型,pojo,map

如果接受的是基本类型的值,那么#{}括号中可以任意或者value

如果#{}获取是的pojo,mybatis通过ognl获取参数值。Ognl就是对象导航语言 属性.属性.属性的方式获取值。

如果传递是map值,#{}中需要的是map的key

${}表示拼接sql,会引入sql注入,不建议使用

${}接受输入参数可以是pojo,基本类型,map

${}如果接受的是基本类型,只能是value

${}接受pojo类型的参数,通过ognl对象导航进行获取

8.4.selectOne和selectList

selectOne是查询单个对象记录,selectList查询多条记录

不能使用selectOne查询selectList的记录

8.5.mybatishibernate区别

Hibernate:hibernate是一个标准的ORM框架,不需要写sql语句,维护关系比叫复杂,sql语句自动生成,对sql语句优化,修改比较困难。

Hibernate的优缺点:

优点:面向对象开发,不需要自己写sql语句。如果进行数据库迁移不需要修改sql语句,只需要修改一下方言。

缺点:hibernate维护数据表关系比较复杂。完全是有hibernate来管理数据表的关系,对于我们来说完全是透明的,不易维护。

Hibernate自动生成sql语句,生成sql语句比较复杂,比较难挑错。

Hibernate由于是面向对象开发,不能开发比较复杂的业务。

应用场景:

适合需求变化较少的项目,比如ERP,CRM等等

Mybatis框架对jdbc框架进行封装,屏蔽了jdbc的缺点,开发简单。

Mybatis只需要程序员关注sql本身,不需要过多的关注业务。对sql的优化,修改比较容易

适应场景:

适合需求变化多端的项目,比如:互联网项目

三.MybatisDao开发

使用dao开发有两种开发方式,一种是使用普通的接口和接口实现类来进行开发

另一种开发方式是使用mapper代理的开发的方式(直接使用接口)

1.sqlSession的使用范围

1.1.sessionFactoryBuidler

SessionFactoryBuidler创建会话工厂sqlSessionFactory

把sessionFactoryBuidler当成一个工具类即可,不需要进行单列模式设计。也

没有进行和spring的整合开发,所以说现在我们还不需要进行单列的设置。直接开发一个工具类,创建sqlSessionFactory的时候直接进行new一个对象即可。

1.2.sqlSessionFactory

sqlSessionFactory生产sqlSession回话,使用单列模式进行创建sqlSessionFactory(工厂一旦创建,只创建一个实例),将mybatis和spring进行整合后使用单列模式进行管理

1.3.sqlSession

sqlSession是面向用户的一个回话接口

sqlSession提供很多操作数据库的方法:selectOne(查询单个对象),selectList(返回单个或者多个对象)

sqlSession线程不安全的,在sqlSession实现类中除了有查询数据库中的方法外还有数据域属性。

sqlSession最好是在方法内部使用。

2.传统的dao的开发方式

2.1.思路

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

在dao实现类里面进行注入sqlSessionFactory,然后通过sqlSessionFactory创建sqlSession

2.2.dao接口



2.3.dao的实现类

publicclass UserDaoImpl implements UserDao {

//给dao层注入SessionFactory对象

//使用构造方法进行注入

public SqlSessionFactory sessionFactory;

public UserDaoImpl(SqlSessionFactory sessionFactory){

this.sessionFactory=sessionFactory;

}

public User findUserbyId(int id) {

//获取sqlSession

SqlSession sqlSession = sessionFactory.openSession();

//根据ID进行查询

User user = sqlSession.selectOne("test.selectUserByID", 30);

return user;

}

public List<User> findUserByUsername(String username) {

//获取Session

SqlSession sqlSession = sessionFactory.openSession();

//使用用户名进行模拟查询

List<User> list = sqlSession.selectList("test.selectUserByUsername", username);

return list;

}

publicvoid insertUser(User user) {

SqlSession sqlSession = sessionFactory.openSession();

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

}

publicvoid deleteUserById(int id) {

SqlSession sqlSession = sessionFactory.openSession();

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

}

}

2.4.测试代码




2.5.原始dao总结

1.dao接口中存在着大量的模版方法,能不能提取出来,大量减轻程序员的压力

2.实现类进行操作数据库时对statement的ID进行硬编码了。

3.sqlSession直接进行设置参数,由于sqlsession使用的泛型,设置参数类型不会报错,这样不利于开发。

3.代理Mapper开发模式

程序员只需要编写dao接口代码,不需要编写实现类代码。大大减轻了程序员的压力

3.1.思路

程序员还需要开发mapper.xml文件。

程序员编写mapper接口需要遵循一些开发规范。Mybatis会自动生成mapper接口实现类代理类。

3.2.开发规范

3.2.1.namespace地址和mapper.xml地址相同

Namespace在这里具有特殊的含义:必须是接口Mapper的接口全路径




3.2.2.dao接口中的方法必须和statement的Id必须一致




3.2.3.参数类型匹配

Mapper接口中的方法输入参数必须和对应的Mapper.xml中的parameterType中的参数匹配

3.2.4.返回值类型匹配

Mapper接口返回值类型必须和对应的mapper.xml中resultType输出类型匹配。

3.2.5.总结

采用代理模式进行开发:更方便,更快捷。

底层会自动调用:selectOne() selectList()

3.3.测试开发

3.3.1.映射文件



3.3.2.测试代码



3.4.总结

3.4.1.底层调用原理

Mapper动态代理方式底层根据返回值类型进行判断调用那个方法:

如果是返回单个对象就调用selectOne

如果是返回集合就调用selectList

3.4.2.mapper接口中参数只能是一个

Mapper接口中的参数只能是一个是否影响系统开发系统维护:

注意:dao层代码是被业务层公用的,即使是dao层代码参数只能是一个

业务层包装成不同类型pojo都可以满足不同业务需求。

持久层方法参数可以是map,基本类型,自定义对象,包装类型.

4.sqlMapConfig.xml

4.1.配置内容

SqlMapConfig.xml中配置的内容和顺序如下:

properties(属性)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

4.2.properties属性文件

sqlMapConfig.xml文件可以引用外部资源文件:



注意:mybatis按照如下的顺序来加载属性:

l 在properties中定义的属性首先被读取

l 然后会读取properties中的resource和url资源

4.3.settings配置

mybatis框架在运行时可以调整一些运行参数。

比如:开启二级缓存、开启延迟加载

全局参数将会影响mybatis的运行行为。

详细参见“学习资料/mybatis-settings.xlsx”文件


4.4.typeAliases(别名)

在sql的xml文件中有很多的statement,statement需要指定parameterType输入参数类型和resultType输出结果类型

如果在开发时每次都写如全路径,不方便开发,此时就可以给parameterType和resultType定义别名

4.4.1.mybatis默认支持别名

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal

4.4.2.自定义别名

4.4.2.1.单个别名定义




引用别名



测试



4.4.2.2.批量定义别名



4.5.类型处理器(typeHandlers)

通常mybatis的typeHandlers完成jdbc类型和Java类型的转换

通常情况下,mybatis提供的类型处理器满足日常的需求,不需要自定义

mybatis支持类型处理器:

类型处理器Java类型JDBC类型
BooleanTypeHandlerBoolean,boolean任何兼容的布尔值
ByteTypeHandlerByte,byte任何兼容的数字或字节类型
ShortTypeHandlerShort,short任何兼容的数字或短整型
IntegerTypeHandlerInteger,int任何兼容的数字和整型
LongTypeHandlerLong,long任何兼容的数字或长整型
FloatTypeHandlerFloat,float任何兼容的数字或单精度浮点型
DoubleTypeHandlerDouble,double任何兼容的数字或双精度浮点型
BigDecimalTypeHandlerBigDecimal任何兼容的数字或十进制小数类型
StringTypeHandlerStringCHAR和VARCHAR类型
ClobTypeHandlerStringCLOB和LONGVARCHAR类型
NStringTypeHandlerStringNVARCHAR和NCHAR类型
NClobTypeHandlerStringNCLOB类型
ByteArrayTypeHandlerbyte[]任何兼容的字节流类型
BlobTypeHandlerbyte[]BLOB和LONGVARBINARY类型
DateTypeHandlerDate(java.util)TIMESTAMP类型
DateOnlyTypeHandlerDate(java.util)DATE类型
TimeOnlyTypeHandlerDate(java.util)TIME类型
SqlTimestampTypeHandlerTimestamp(java.sql)TIMESTAMP类型
SqlDateTypeHandlerDate(java.sql)DATE类型
SqlTimeTypeHandlerTime(java.sql)TIME类型
ObjectTypeHandler任意其他或未指定类型
EnumTypeHandlerEnumeration类型VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。

4.6.映射配置

4.6.1.通过resource加载单个配置文件



4.6.2.url加载绝对路径映射文件

使用完全限定路径

如:<mapper url="file:///D:\workspace_spingmvc\mybatis01\config\sqlmap\User.xml" />

4.6.3.接口class加载单个配置文件




根据以上要求:接口和配置文件必须在同一个目录



或者:



4.6.4.package批量加载Mapper文件



5.输入映射(parameterType)

通过parameterType指定输入参数类型,参数类型可以是基本类型,pojo,map类型

5.1.传递pojo包装类对象

5.1.1.需求

需求:完成用户的综合信息查询,输入参数比较复杂。(包含用户信息和其他信息)

5.1.2.定义包装类型pojo




注意:我们为什么不直接使用User来进行封装参数呢?

这是因为我们可以在隔离类里面进行封装很多参数,并且我们还有一些其他和业务不相关的查询条件。我们都可以定义在custom中。

在开发中和复杂查询条件也可直接封装在Javabean中,这样叫做非持久化属。

还有一种就是我们进行隔离开发,在定义一个公共封装属性的类。

5.1.3.mapper.xml文件

5.1.4.mapper接口代码



5.1.5.测试代码



5.2.传递Map

5.2.1.映射文件



5.2.2.接口代码



5.2.3.测试代码



6.输出映射(resultType|resultMap)

使用resultType进行查询结果映射,只要数据库列名和javabean的属性相同就可以映射成功

如果不相同:resultMap进行映射

如果查询出来对象的列名和javabean的属性全部不一致,不会创建javabean对象。

如果查询结果中仅有一个列名和属性一致,javabean对象就会被创建。

6.1.resultType

6.1.1.输出简单类型

6.1.1.1.需求

查询用户综合信息总记录数,和用户列表就可以实现分页

6.1.1.2.映射文件



6.1.1.3.测试代码



总结:输出结果是简单类型,可以使用简单类型进行映射

6.1.2.输出pojo

无论resultType返回结果是单个对象还是List集合对象,resultType返回类型都是一样的。

但是在代码中需要指定返回值结果类型。

尤其是在接口代理中:mybatis是根据返回值类型进行判断调用selectOne还是selectList

6.1.2.1.输出pojo对象



6.1.2.2.输出pojo集合



6.2.resultMap

mybatis使用resultMap完成高级映射

使用方法:如果mybatis查询结果列名和Javabean属性不一致,通过resultMap把javabean属性和数据库的列名进行关系映射。

6.2.1.映射文件



6.2.2.输出类型(resultMap)

使用resultMap作为输出结果集类型:

如果不在同一个Mapper文件中,需要指明包名。




6.2.3.接口代码



6.2.4.测试代码



6.3.总结

使用resultType进行映射:pojo中的属性必须和查询的类名相同

使用resultMap进行映射:pojo中的属性和查询的类名可以相同也可以不相同

7.动态sql(掌握)

7.1.什么是动态sql

Mybatis对sql进行灵活操作,可以通过mybatis语法的判断对sql进行灵活封装,拼接

7.2.需求

用户信息综合查询列表和用户信息查询总记录使用动态sql进行查询

对查询条件进行判断:

如果值为空就不能进行sql的拼接

7.3.映射文件



7.4.接口代码



7.5.测试代码




7.6.sql片段

7.6.1.需求

将上面的动态sql判断代码进行抽取,组成一个sql片段,其他的statement可以引用这个片段,方便程序员开发。

7.6.2.定义sql片段



7.6.3.引用sql片段



7.7.foreach

向mybatis传递数组,或者List集合使用foreach就可以解析

7.7.1.需求

在用户综合信息查询时使用多个ID进行查询:

SELECT * FROM USER WHERE id=1 OR id=10 OR id=16

SELECT * FROM USER WHERE id IN(1,10,16)

单独传递集合和数组

7.7.2.输入参数中定义集合List<Integer>



7.7.3.映射文件(修改)

WHERE id=1 OR id=10 OR id=16

在查询条件中,查询条件定义成一个sql片段,需要修改sql片段。



7.7.4.测试代码



7.7.5.另一个IN(…)实现



7.8.补充内容

多参数集合查询

即除了包含in条件,还包含至少一个其它条件的)

select * from student where class = #{class} and level in (1,2,3,4)

对第二种的实现,必须掌握StudentWapper.xml中语法。

如下:

1) 接口代码

List getStudentsByLevels(Map paramMap)

其中这个map中放的是:

map.put("levels", new String[]{1,2,3,4});

map.put("class", "good");

注:

#这里的levels和下面xml中的collection中的相对应

#对于字符串的in,MyBatis已作处理,不需要再自己给数组中的每个元素加上单引号。

2)xml文件中配置

<select id="getStudentsByLevels" resultType="xxx.Student">

select * from student where class = #{class} and level in

<foreach collection="levels" item="item" open="(" separator="," close=")">

#{item}

</foreach>

<select/>

更新使用set动态更新

<update id="updateAuthorIfNecessary">

update Author

<set>

<if test="username != null">username=#{username},</if>

<if test="password != null">password=#{password},</if>

<if test="email != null">email=#{email},</if>

<if test="bio != null">bio=#{bio}</if>

</set>

where id=#{id}

</update>

Trim

trim是更灵活的去处多余关键字的标签,他可以实践where和set的效果、

choose (when, otherwise)

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。而使用if标签时,只要test中的表达式为true,就会执行if标签中的条件。MyBatis提供了choose 元素。if标签是与(and)的关系,而choose是或(or)的关系。

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default


更多资源分享就在【Java帮帮】微信公众号与QQ空间

相关推荐

C++开发必知的内存问题及常用的解决方法-经典文章

1.内存管理功能问题由于C++语言对内存有主动控制权,内存使用灵活和效率高,但代价是不小心使用就会导致以下内存错误:omemoryoverrun:写内存越界odoublefree:同一块内...

缓存用不好,系统崩得早!10条军规让你成为缓存高手

凌晨三点,我被电话惊醒:“苏工!首页崩了!”监控显示:缓存命中率0%,数据库QPS10万+,线程阻塞2000+。根本原因竟是同事没加缓存!不会用缓存的程序员,就像不会刹车的赛车手——...

彻底搞清楚内存泄漏的原因,如何避免内存泄漏,如何定位内存泄漏

作为C/C++开发人员,内存泄漏是最容易遇到的问题之一,这是由C/C++语言的特性引起的。C/C++语言与其他语言不同,需要开发者去申请和释放内存,即需要开发者去管理内存,如果内存使用不当,就容易造成...

Java中间件-Memcached(Java中间件大全)

一、知识结构及面试题目分析缓存技术的大规模使用是互联网架构区别于传统IT技术最大的地方,是整体高并发高性能架构设计中是重中之重的关键一笔,也是互联网公司比较偏好的面试题目。按照在软件系统中所处位置...

linux内存碎片防治技术(linux内存碎片整理)

推荐视频:90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc原理剖析Linux内核内存分配与回收Linuxkernel组织管理物理内存的方式是buddysystem(伙...

Redis主从架构详解(redis主从配置详细过程)

Redis主从架构搭建Redis主节点配置创建主节点目录(/opt/redis-master),复制redis.conf到该目录下,redis.conf配置项修改#后台启动daemonizeyes...

揭开CXL内存的神秘面纱(内存c1)

摘要:现代数据中心对内存容量的高需求促进了内存扩展和分解方面的多条创新线,其中一项获得极大关注的工作是基于ComputeeXpressLink(CXL)的内存扩展。为了更好地利用CXL,研究人员建...

一文彻底弄懂 TPS RPS QPS(tps cps)

以下是关于RPS、QPS、TPS的核心区别与关联的总结,结合实际场景和优化建议:一、核心定义与区别RPS:RequestsPerSecond每秒请求数客户端到服务器的完整请求数量Web服务...

用Redis的“集合”找出你和朋友的“共同关注”

你是不是在刷抖音、微博、小红书的时候,常常会看到这样的提示:“你和XXX有共同关注的博主/朋友”?或者当你关注了一个新的明星,系统会推荐“你的朋友YYY也关注了这位明星”?这个看似简单的功能背后,其实...

WOT2016彭哲夫:科班出身开发者对运维人员的期许

“运维与开发”是老生常谈的话题,前几天和一个运维人聊天,TA说一些公司运维岗位都不公开招聘了,这让众多运维人员情何以堪?是运维的岗位真的饱和了?是找到合适的运维人才难?还是有这样那样的因素?带着这些疑...

Java程序员最常用的20%技术总结(java程序员要掌握什么)

我听说编程语言,经常使用的是其中20%的技术。在Java这门语言中,这20%包括哪些内容?找到一份Java初级程序员的工作,有哪些是必须掌握的,有哪些是可以现学现卖的?一个完整的Javaweb项目,有...

秒杀系统实战(四)| 缓存与数据库双写一致性实战

前言微笑挖坑,努力填坑。————已经拥有黑眼圈,但还没学会小猪老师时间管理学的蛮三刀同学本文是秒杀系统的第四篇,我们来讨论秒杀系统中「缓存热点数据」的问题,进一步延伸到数据库和缓存的...

头条评论精灵翻牌子(头条评论精灵翻牌子怎么弄)

关于“头条评论精灵翻牌子”功能,这通常是指平台通过算法或运营手段,将用户的优质评论随机或定向推送到更显眼的位置(如信息流顶部、独立曝光位等),以提升互动率和用户参与感。以下是详细解析和建议:一、功能理...

15个程序员们都应该知道的大模型高级提示词指令模板和示例

作为程序员你如何写大模型指令?你写的指令是不是更专业呢?下面是15个程序员使用的专业的大模型指令,如果早知道可以能节省你很多时间。这些指令可以用在chatgpt,deepseek等大模型。1.一键...

MyBatis-Plus内置的主键生成策略有大坑,要注意!

昨天小伙伴使用Mybaits-Plus开发的项目线上(集群、K8S)出现了主键重复问题,其报错如下:Mybatis-Plus启动时会通过com.baomidou.mybatisplus.core.to...

取消回复欢迎 发表评论: