Mybatis笔记

Mybatis笔记

采用了ORM思想解决了实体类和数据库表映射的问题。对JDBC进行了封装,屏蔽了JDBCAPI底层的访问细节,避免我们与jdbc的api打交道,就能完成对数据的持久化操作。

O–Object java对象

R- Relation 关系,就是数据库中的一张表

M-mapping 映射

一、Mybatis入门案例

1.创建maven项目,添加Mybatis的jar依赖

<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>

2.编写Mybatis的配置文件

一般情况下:配置文件的名称可以自定义,课程中使用mybatis.xml。配置文件放置在java/resources中。

头文件去官网中复制粘贴。在这里给大家提供一个中文的网站。

https://mybatis.org/mybatis-3/zh/index.html

<?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> <!--配置 mybatis 环境--> <environments default="development"> <!--id:数据源的名称--> <environment id="development"> <!--事务类型:使用 JDBC 事务,使用 Connection 的提交和回滚--> <transactionManager type="JDBC"></transactionManager> <!--数据源 dataSource:创建数据库 Connection 对象 type: POOLED 使用数据库的连接池 --> <dataSource type="POOLED"> <!--连接数据库的四大参数 注意数据库版本使用的是MySQL8,如果是mysql5的话,driver和url都不一样,参考学过的JDBC--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis? useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> </configuration>

3.编写实体类

实体类中的属性必须与表中的列名保持一致。

4.编写ORM映射文件

我们是针对实体类Team.java和表Team进行ORM映射.

Mybatis框架中,ORM映射是针对SQL语句进行,Mybatis框架将SQL语句抽取到了XML中。所以我们需要针对每个实体类编写XML映射文件。

4.1 XML映射文件必须与实体类在同一个包下面(也可以存放在resource资源包下,但是存放的包路径要一致)。
4.2 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="名称必须与映射的类的名字一致,是完全限定名"--> <mapper namespace="com.kkb.pojo.Team"> <!-- id="自定义名称,id不能重复;相当于dao中的方法名称" resultType="使用的要求:实体类中的属性名与表中的列名一致" --> <select id="queryAll" resultType="com.kkb.pojo.Team"> select * from team; </select> </mapper>

5.将映射文件注册到mybatis的配置文件中

<?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> <environments default="development"> <environment id="development"> ...... </environment> </environments> <!-- 注册映射文件 --> <mappers> <mapper resource="com/kkb/pojo/Team.xml"/> </mappers> </configuration>

6.配置映射文件的扫描位置

pom.xml文件配置映射文件的扫描路径

<build> <resources> <resource> <directory>src/main/java</directory><!--所在的目录--> <includes><!--包括目录下的.properties,.xml 文件都会扫描到--> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering></resource> </resources> <plugins> //省略 </plugins> </build>

7.使用Mybatis框架的核心接口测试

package com.kkb.test; import com.kkb.pojo.Team; import com.mysql.cj.Session; 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.junit.Test; import java.io.IOException; import java.io.Reader; import java.util.List; /*** ClassName: TeamTest * Team 测试类 * @author wanglina * @version 1.0 */ public class TeamTest { //mybatis的配置文件--相当于创建工厂的图纸 private String resource="mybatis.xml"; @Test public void testFindAll(){ try {//1、读取mybatis的配置文件 Reader reader = Resources.getResourceAsReader(resource) ; //2、创建SqlSessionFactory对象,目的是获取sqlSession--根据图纸创建工厂 SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(reader); //3、创建可以执行SQL语句的SqlSession--工厂创建产品 SqlSession sqlSession = sqlSessionFactory.openSession(); //4、执行SQL语句 List<Team> teamList = sqlSession.selectList("com.kkb.pojo.Team.findAll"); //5、循环输出查询的结果 for (Team team : teamList) { System.out.println(team); }//6、关闭SqlSession,释放资源 sqlSession.close(); } catch (IOException e) { e.printStackTrace(); } } }

8.入门案例的增删改查

Team.xml的映射文件中添加:

8.1根据ID查询单个对象
<!--根据ID查询 parameterType="参数的类型",目前只支持一个参数 where teamId=#{id}: #{id}表示参数 id-自定义,只需要符合命名规范即可,没有实际对应意义 --> <select id="findById" parameterType="int" resultType="com.kkb.pojo.Team"> select * from team where teamId=#{id} </select>

测试类中添加如下内容:

private SqlSession sqlSession; @Test public void testFindById(){ Team team=sqlSession.selectOne("com.kkb.pojo.Team.queryById",1001); System.out.println(team); }@Before public void before() throws IOException { //1、读取mybatis的配置文件 Reader reader = Resources.getResourceAsReader(resource) ; //2、创建SqlSessionFactory对象,目的是获取sqlSession--根据图纸创建工厂 SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(reader);//3、创建可以执行SQL语句的SqlSession--工厂创建产品 sqlSession = sqlSessionFactory.openSession(); }@After public void after(){ sqlSession.close(); }
8.2增删改

在增删改的java代码运行时,需要手动提交

<!--删除一个球队 --> <delete id="del" > delete from team where teamId=#{id} </delete> <!--更新一个球队 --> <update id="update" parameterType="com.kkb.pojo.Team"> update team set teamName=#{teamName},location=#{location} where teamId=#{teamId} </update> <!--添加一个球队 parameterType="com.kkb.pojo.Team" 将对象作为参数, #{值} 值必须是实体类中的属性名称,其实就是占位符? --> <insert id="add" parameterType="com.kkb.pojo.Team" > INSERT INTO `team` (`teamName`, `location`, `createTime`) VALUES (#{teamName}, #{location}, #{createTime}) </insert>

二、Mybatis对象分析

1 Resources

Resources 类,顾名思义就是资源,用于读取资源文件。其有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象。

2 SqlSessionFactoryBuilder

SqlSessionFactory 的 创 建 , 需 要 使 用 SqlSessionFactoryBuilder 对 象 的 build() 方 法 。 事实上使用SqlSessionFactoryBuilder的原因

是将SqlSessionFactory这个复杂对象的创建交由Builder来执行,也就是使用了建造者设计模式。

建造者模式: 又称生成器模式,是一种对象的创建模式。 可以将一个产品的内部表象与产品的生成过程分割开来, 从而可以使一个建造过程生成具有 不同的内部表象的产品(将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示). 这样用户只需指定需要建造的类型就可 以得到具体产品,而不需要了解具体的建造过程和细节. 在建造者模式中,角色分指导者(Director)与建造者(Builder): 用户联系指导者, 指导者指挥建造者, 最后得到产品. 建造者模式可以强制实行 一种分步骤进行的建造过程.

3 SqlSessionFactory

SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用只需要一个该对象即可。创建SqlSession 需要使用 SqlSessionFactory 接口的的 openSession()方法。

默认的 openSession()方法没有参数,它会创建有如下特性的 SqlSession: 
	1、会开启一个事务(也就是不自动提交)。 
	2、将从由当前环境配置的 DataSource 实例中获取 Connection 对象。事务隔离级别将会使用驱动或数据源的默认设置。 
	3、预处理语句不会被复用,也不会批量处理更新。 
openSession(true):创建一个有自动提交功能的 
SqlSession openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交 
openSession():同 openSession(false)

4 SqlSession

  • SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以SqlSession 对象的创建开始,以SqlSession 对象的关闭结束。
  • SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将其关闭。再次需要会话,再次创建。
  • SqlSession 在方法内部创建,使用完毕后关闭。
  • SqlSession 类中有超过 20 个方法,我们常用的几乎都是执行语法相关的方法。
  • 这些方法被用来执行定义在 SQL 映射的 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 语句。它们都会自行解释,每一句都使用语句的 ID 属性和参数对象,参数可以是原生类型(自动装箱或包装类)、JavaBean、POJO 或 Map。
<T> T selectOne(String statement, Object parameter) <E> List<E> selectList(String statement, Object parameter) <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey) int insert(String statement, Object parameter) int update(String statement, Object parameter) int delete(String statement, Object parameter) <!--selectOne 和 selectList 的不同仅仅是 selectOne 必须返回一个对象或 null 值。如果返回值多于一个,那么就会抛出异常。 selectMap 稍微特殊一点,因为它会将返回的对象的其中一个属性作为 key 值,将对象作为 value 值,从而将多结果集转为 Map 类型值。因为 并不是所有语句都需要参数,所以这些方法都重载成不需要参数的形式。 -->

5 Mybatis架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-epVhZish-1627200025262)(C:\Users\柳佳宇\AppData\Local\Temp\1621471223880.png)]

1、Mybatis.xml文件是mybatis框架的全局配置文件,配置了mybatis框架运行的环境等信息。 Mapper1.xml.....是SQL的映射文件,文件中配置了所有的操作数据库的sql语句,这些文件需要在全局配置文件中加载。 
2、通过mybatis环境等配置信息构建SqlSessionFactroy ,相当于是产生连接池 
3、由会话工厂创建SqlSession即会话(连接),操作数据库需要通过SqlSession进行的。 
4、Mybatis底层自定义了Executor执行器的接口操作数据库,Executor接口有两个实现,一个基本的执行器,一个是缓存的执行器。 
5、Mapped statement 也是mybatis框架一个底层的封装对象,他包装了mybatis配置信息以及sql映射信息。Mapper.xml文件中的一个SQL语 句对应一个Mapped statement对象,sql的id就是Mapped statement的id。 
6、Mapped statement对SQL执行输入参数的定义,输入参数包括HashMap、基本类型、pojo,Executor通过Mapped statemen在执行SQL语句 前将输入java对象映射到sql语句中,执行完毕SQL之后,输出映射就是JDBC编码中的对preparedStatement 执行结果的定义。

三、配置日志文件

1 添加jar依赖

<dependency> 
    <groupId>log4j</groupId> 
    <artifactId>log4j</artifactId> 
    <version>1.2.17</version> </dependency>

2 添加日志配置文件–在resource下添加log4j.properties配置文件

# Global logging configuration info warning error 
log4j.rootLogger=DEBUG,stdout 
# Console output... 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

3 在mybatis配置文件中添加日志的配置

<configuration> 
    <!--配置日志,注意顺序:查看属性点击configuration进入查看即可--> 
    <settings> 
        <setting name="logImpl" value="LOG4J" /> 
    </settings> ......

四、使用原有的Dao方式开发->只是为了熟悉一下,

1、创建工具类

1.1 ThreadLocal------让sqlsession线程安全的方法

ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本, 是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。

1.2 工具类—创建一个连接操作的工具类
package com.kkb.utils; 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.Reader; /*** ClassName: SessionUtil * 连接操作的工具类 * @author wanglina * @version 1.0 */ public class MybatisUtil { private static ThreadLocal<SqlSession> threadLcoal = new ThreadLocal<SqlSession>(); private static SqlSessionFactory SqlSessionFactory; /**** 加载配置文件 */ static{ try{Reader reader = Resources.getResourceAsReader("mybatis.xml"); SqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); }catch(IOException e){ e.printStackTrace(); throw new RuntimeException(e); } }/*** 获取SqlSession * @return */ public static SqlSession getSqlSession(){ //从当前线程获取 SqlSession sqlSession = threadLcoal.get(); if(sqlSession == null){ sqlSession = SqlSessionFactory.openSession(); //将sqlSession与当前线程绑定 threadLcoal.set(sqlSession); }return sqlSession; }/*** 关闭Session */ public static void closeSqlSession(){ //从当前线程获取 SqlSession sqlSession = threadLcoal.get(); if(sqlSession != null){ sqlSession.close(); threadLcoal.remove(); } } }

2、创建TeamDao接口和实现类

package com.kkb.dao; import com.kkb.pojo.Team; import java.util.List; /*** ClassName: TeamDao * 原有的dao写法 * @author wanglina * @version 1.0 */ public interface TeamDao { List<Team> queryAll(); Team queryById(Integer teamId); int add(Team team); int update(Team team); int del(Integer teamId); }
package com.kkb.dao; import com.kkb.pojo.Team; import com.kkb.utils.MybatisUtil; import org.apache.ibatis.session.SqlSession; import java.util.List; /*** ClassName: TeamDao * Team的数据访问层 * @author wanglina * @version 1.0 */ public class TeamDaoImpl implements TeamDao { /*** 查询所有球队 * @return */ public List<Team> queryAll(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); List<Team> teamList = sqlSession.selectList("com.kkb.pojo.Team.findAll"); return teamList; }/*** 根据id查询单个球队 * @param teamId * @return */ public Team queryById(int teamId){ SqlSession sqlSession = MybatisUtil.getSqlSession(); Team team=sqlSession.selectOne("com.kkb.pojo.Team.findById",teamId); return team; }/*** 添加球队 * @param team * @return */ public int add(Team team){ SqlSession sqlSession = MybatisUtil.getSqlSession(); int num = sqlSession.insert("com.kkb.pojo.Team.add", team); sqlSession.commit();//必须提交才能让增删改生效 return num; }/*** 更新球队 * @param team * @return */ public int update(Team team){ SqlSession sqlSession = MybatisUtil.getSqlSession(); int num = sqlSession.insert("com.kkb.pojo.Team.update", team); sqlSession.commit();//必须提交才能让增删改生效 return num; }/*** 根据id删除球队 * @param teamId * @return */ public int del(int teamId){ SqlSession sqlSession = MybatisUtil.getSqlSession();int num = sqlSession.insert("com.kkb.pojo.Team.del", teamId); sqlSession.commit();//必须提交才能让增删改生效 return num; } }

五、使用Mapper的接口编写Mybatis项目—重点!!!

1、什么是Mapper接口

在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么实质性的工作,它仅仅就是通过 SqlSession 的相关API 定位到映射文件 mapper 中相应 id 的 SQL 语句,真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。

所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对DB 进行操作。这种对 Dao 的实现方式称为Mapper接口的动态代理方式。

Mapper 动态代理方式无需程序员实现 Dao 接口。接口是由 MyBatis 结合映射文件自动生成的动态代理实现的。

2、实现步骤------重点!!!

2.1 编写接口TeamMapper.java
package com.kkb.mapper; import com.kkb.pojo.Team; import java.util.List; /*** ClassName: TeamMapper * Mapper接口 * @author wanglina* @version 1.0 */ public interface TeamMapper { List<Team> queryAll(); Team queryById(int teamId); int add(Team team); int update(Team team); int del(int teamId); }

创建TeamMapper.xml文件,与Team.xml内容几乎一样,只有namespace="com.kkb.mapper.TeamMapper"修改为接口的完全限定名

<?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.kkb.mapper.TeamMapper"> <!--省略内容,复制Team.xml中的内容即可--> </mapper>

在mybatis.xml配置文件中注册映射文件

<mappers> 
    <!--省略其他--> <mapper resource="com/kkb/mapper/TeamMapper.xml"/> 
</mappers>
2.2 getMapper方法获取代理对象

只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。

package com.kkb.test; import com.kkb.dao.TeamDao; import com.kkb.dao.TeamDaoImpl; import com.kkb.mapper.TeamMapper; import com.kkb.pojo.Team; import com.kkb.utils.MybatisUtil; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.Date; import java.util.List; /*** ClassName: TeamDaoTest * TeamMapper的测试类 * @author wanglina * @version 1.0 */ public class TeamMapperTest { private SqlSession sqlSession=MybatisUtil.getSqlSession(); @Test public void test01(){ TeamMapper teamDao= sqlSession.getMapper(TeamMapper.class); //添加 Team team=new Team(); team.setTeamName("勇士"); team.setLocation("金州"); team.setCreateTime(new Date()); int num=teamDao.add(team); sqlSession.commit();//必须提交才能让增删改生效 System.out.println(num); //更新 Team team1 = teamDao.queryById(1001); team1.setTeamName("lina的球队"); num = teamDao.update(team1); sqlSession.commit();//必须提交才能让增删改生效 System.out.println(num); //删除 num=teamDao.del(1001); sqlSession.commit();//必须提交才能让增删改生效 System.out.println(num); //查询所有 List<Team> teams = teamDao.queryAll(); teams.forEach(t-> System.out.println(t)); } }

3 实现原理—看源码

六、增删改查中的细节—特殊操作

6.1 插入数据的时候获取自增的id

6.1.1 案例准备–数据库、实体类、mapper、接口
6.1.2 修改配置文件
添加GameRecordMapper.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="名称必须与映射的类的名字一致,是完全限定名"--> <mapper namespace="com.kkb.mapper.GameRecordMapper"> <!--添加一条比赛记录 --> <insert id="add" parameterType="com.kkb.pojo.GameRecord" > <!--插入数据之前先获取36位字符串作为id放入属性recordId中 order="AFTER/BEFORE" 在insert执行之前还是之后 resultType="返回值的类型" --> <selectKey keyProperty="recordId" order="BEFORE" resultType="java.lang.String"> select uuid() </selectKey> INSERT INTO `mybatis`.`gamerecord` (`recordId`, `homeTeamId`, `gameDate`, `score`, `visitingTeamId`) VALUES (#{recordId}, #{homeTeamId},default, #{score}, #{visitingTeamId}) </insert> </mapper>
修改TeamMapper.xml文件中的insert节点
<!--添加一个球队 parameterType="com.kkb.pojo.Team" 将对象作为参数, #{值} 值必须是实体类中的属性名称,其实就是占位符? --> <insert id="add" parameterType="com.kkb.pojo.Team" > <!--新增成功之后将自增的ID赋值给参数属性teamId keyProperty:表示新增的id值赋值到哪个属性值红 order:AFTER/BEFORE两个取值,表示selectKey中的sql语句在insert语句之前还是之后执行 resultType:表示返回值类型 --> <selectKey keyProperty="teamId" order="AFTER" resultType="java.lang.Integer"> select LAST_INSERT_ID() </selectKey> INSERT INTO `team` (`teamName`, `location`, `createTime`) VALUES (#{teamName}, #{location}, #{createTime}) </insert>

6.2 输入映射—输入多个参数

6.2.1 parameterType

parameterType:接口中方法参数的类型,类型必须是完全限定名或别名(稍后讲别名)。该属性非必须,因为Mybatis框架能自行判断具体传入语句的参数,默认值为未设置(unset)。

6.2.1.1—方式一
TeamMapper.xml配置文件中添加如下:
<!--多个参数:标签中不需要parameterType属性 方式1:通过下标索引的方式,还有两种方式(太难记了,可以忽略,看看演示就好啦) select * from team where teamId &gt;=#{arg0} and teamId &lt;=#{arg1}; 也可以,注意下表索引 细节1:mybatis3.3版本之前:可以直接写#{0} #{1} 从mybatis3.4开始:#{arg0} #{arg1}... 或者是 #{param1} #{param2}... 细节2:sql语句中不能使用小于号,使用转移符号替换;大于号没有限制,也可以使用转义符号替换&gt; --> <select id="queryByRange1" resultType="com.kkb.pojo.Team"> select * from team where teamId >=#{param1} and teamId &lt;=#{param2}; </select>
6.2.1.2—方式二 通过@Param注解

在方法的形参前面加入@Param(“自定义参数名称”),mapper文件中使用#{自定义参数名称}的方式传参。

TeamMapper接口添加如下内容:
List<Team> queryByRange2(@Param("min") Integer min, @Param("max") Integer max);
TeamMapper.xml配置文件中添加如下:
<!--方式2:通过注解的方式: #{}中的名称必须与接口的方法中的参数注解@Param()保持一致 select * from team where teamId >=#{param1} and teamId &lt;= #{param2}; 不推荐,但是语法也是正确的,但是不能使用arg0,arg1...... --> <select id="queryByRange2" resultType="com.kkb.pojo.Team"> select * from team where teamId >=#{min} and teamId &lt;= #{max}; </select>
6.2.1.3—方式三 通过map来传递多个参数

Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key,Object 类型的值存储参数。 mapper 文件使用 # { key } 引用参数值

TeamMapper接口添加如下内容:
List<Team> queryByRange3(Map<String,Object> map);
TeamMapper.xml配置文件中添加如下:
<!--方式3:通过map来传递多个参数:映射文件中的参数占位符必须和map中的String类型的字段名称一样--> <select id="queryByRange3" resultType="com.kkb.pojo.Team"> select * from team where teamId >=#{min} and teamId &lt;= #{max}; </select>
6.2.1.4—方式四 通过pojo类传递多个参数

与map传递多个参数类似,要求映射文件中的参数占位符必须和pojo类中的属性完全一致。

实体类—用于存放要输入参数的类:
TeamMapper接口添加如下内容:
List<Team> queryByCondition(QueryVO vo);//vo为参数的实体类
TeamMapper.xml配置文件中添加如下:
<!--方式4:通过pojo类传递多个参数:映射文件中的参数占位符必须和pojo类中的字段完全一致--> <select id="queryByCondition" resultType="com.kkb.pojo.Team"> select * from team where teamId>=#{min} and teamId&lt;=#{max} and teamName like #{name} and location=#{location} </select>

6.3 #{} 和 ${}的区别–面试中喜欢出的考题!!!

6.3.1 #{}
#{}:表示一个占位符,通知Mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替sql 语句的“?”。这个是Mybatis 中的首选做法,安全迅速。
6.3.1 ${}
${}:表示字符串原样替换,通知Mybatis 使用$包含的“字符串”替换所在位置。使用 Statement或者PreparedStatement 把 sql 语句和${}的内容连接起来。一般用在替换表名,
列名,不同列排序等操作。

6.4 输出映射

6.4.1 resultType

resultType: 执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。如果返回的是集合,设置的是集合元素的类型,而不是集合本身。resultType 和 resultMap,不能同时使用。

6.4.1.1 输出简单类型
TeamMapper接口添加如下内容:
int getCount();
TeamMapper.xml配置文件中添加如下:
<!-- 只有返回的结果是单行的时候,返回值类型才可以指定为基本类型 如果是单行多列,也取不到后面的列的值; 如果返回多行会报异常:TooManyResultsException--> <select id="getCount" resultType="java.lang.Integer"> select count(teamId) from team </select>
6.4.1.2 输出pojo类型
TeamMapper.xml配置文件中添加如下:
<!--接口方法返回是集合类型,但是映射文件中的resultType需要指定集合中的类型,不是集合本身。--> <select id="queryAll" resultType="com.kkb.pojo.Team"> select * from team; </select>
6.4.1.3 输出Map类型

当我们只需要查询表中几列数据的时候可以将sql的查询结果作为Map的key和value。一般使用的是Map<Object,Object>.

Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录会抛出TooManyResultsException异常。

如果有多行,使用List<Map<Object,Object>.

TeamMapper接口添加如下内容:
Map<Object,Object> queryTwoColumn(int teamId); List<Map<Object,Object>> queryTwoColumnList();
TeamMapper.xml配置文件中添加如下:
<select id="queryTwoColumn" resultType="java.util.HashMap"> select teamName,location from team where teamId=#{id} </select> <select id="queryTwoColumnList" resultType="java.util.HashMap"> select teamName,location from team </select>
6.4.2 resultMap

resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。

常用在列名和 java 对象属性名不一样的情况。

使用方式:
1.先定义 resultMap,指定列名和属性的对应关系。
2.在中把resultType替换为resultMap
TeamMapper.xml映射文件添加:
<!--resultMap 和resultType不能同时出现 resultMap:是引用的自己创建resultMap的id--> <select id="queryAll2" resultMap="baseResultMap"> select * from team; </select><!--创建resultMap:相当于自己编写表中的列与实体类中的属性的映射 id:resultMap的名称,要求唯一 type:期待要映射为java的类型 --> <resultMap id="baseResultMap" type="com.kkb.pojo.Team"> <!--一般主键列用id,其余列用result column:表示数据库表中的列名,不区分大小写 property:表示实体类中的对应的属性名,区分大小写 javaType:实体类中的对应的属性的类型,可以省略,mybatis会自己推断 jdbcType="数据库中的类型column的类型" 一般省略 --> <id column="teamId" property="teamId" javaType="java.lang.Integer" ></id> <result column="teamName" property="teamName" javaType="java.lang.String"></result> <result column="location" property="location" javaType="java.lang.String"></result> <result column="createTime" property="createTime" javaType="java.util.Date"></result> </resultMap>
6.4.3 数据库表中列与实体类属性不一致的处理方式
6.4.3.1 使用列别名和resultType

映射文件UsersMapper.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"> <mapper namespace="com.kkb.mapper.UsersMapper"> <!--方式1:resultType中的实体类的属性作为查询语句中的别名,让别名和属性保持一致--> <select id="queryByID" resultType="com.kkb.pojo.Users"> select user_id as userId,user_name as userName,user_age as userAge from users where user_id=#{id}; </select> </mapper>
6.4.3.2 使用resultMap

映射文件UsersMapper.xml添加如下内容:

<!--方式2:通过resultMap自行映射--> <select id="queryByID2" resultMap="baseMap"> select * from users where user_id=#{id}; </select> <resultMap id="baseMap" type="com.kkb.pojo.Users"> <id column="user_id" property="userId"/> <result column="user_name" property="userName"/> <result column="user_age" property="userAge"/> </resultMap>

七、Mybatis的全局配置文件

案例中使用的 mybatis.xml就是Mybatis的全局配置文件。

全局配置文件需要在头部使用约束文件。

<?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">

7.1 配置的内容—顺序很重要

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

configuration(配置) 
	properties--属性:加载外部的配置文件,例如加载数据库的连接信息 
	Settings--全局配置参数:例如日志配置 
	typeAliases--类型别名 
	typeHandlers----类型处理器 
	objectFactory-----对象工厂 
	Plugins------插件:例如分页插件 
	Environments----环境集合属性对象 
		environment(环境变量) 
			transactionManager(事务管理器) 
			dataSource(数据源) 
	Mappers---映射器:注册映射文件用

7.2 属性(properties)

  • 属性可以在外部进行配置,并可以进行动态替换。我们既可以在 properties 元素的子元素中设置(例如DataSource节点中的properties节点),也可以在 Java 属性文件中配置这些属性。
  • 数据源中有连接数据库的四个参数数据,我们一般都是放在专门的属性文件中,mybatis的全局配置文件直接从属性文件中读取数据即可。
7.2.1、在 resources 目录创建 jdbc.properties 文件,文件名称可以自定义。
jdbc.driver=com.mysql.cj.jdbc.Driver 
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT 
jdbc.username=root 
jdbc.password=root
7.2.2、mybatis的全局配置文件引入属性文件
<properties resource="jdbc.properties"/>
7.2.3、使用属性文件中的值
<dataSource type="POOLED"> 
    <property name="driver" value="${jdbc.driver}"/> 
    <property name="url" value="${jdbc.url}"/> 
    <property name="username" value="${jdbc.username}"/> 
    <property name="password" value="${jdbc.password}"/> 
</dataSource>

7.3 设置 settings

MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为.例如我们配置的日志就是应用之一。其余内容参考http://xn–mybatis-m43kk2dt42i5bzbkmwea1425byor/

<!--配置日志--> 
<settings> 
    <setting name="logImpl" value="LOG4J"/> 
</settings>

7.4 类型别名 typeAliases

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

7.4.1 Mybatis中已经支持的别名
别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator
7.4.2 自定义别名—很重要
<!--自定义类型别名--> 
<typeAliases> 
    <!--对单个的实体类定义别名--> 
    <typeAlias type="com.kkb.pojo.Team" alias="Team"/> 
    <!--推荐写法:批量定义别名:扫描指定包下的所有类,同时别名定义为类名,别名的首字母大小写都可以--> 
    <package name="com.kkb.pojo"/> </typeAliases>

7.5 映射器 Mappers

配置有多种方式:

7.5.1、 使用相对于类路径的资源引用
语法:<mapper resource=""/> 
使用相对于类路径的资源,从 classpath 路径查找文件 例如:
<mapper resource="com/kkb/mapper/TeamMapper.xml" />
7.5.2、使用映射器接口实现类的完全限定类名
语法:<mapper class=""/> 
使用的mapper接口的完全限定名 
要求:接口和映射文件同包同名 
例如<mapper class="com.kkb.mapper.GameRecordMapper"/>
7.5.3、将包内的映射器接口实现全部注册为映射器—推荐
语法:<package name=""/> 
指定包下的所有Mapper接口 
如:<package name="com.kkb.mapper"/> 
注意:此种方法要求 Mapper接口名称和 mapper 映射文件名称相同,且在同一个目录中。

7.6 dataSource标签

Mybatis 中访问数据库支持连接池技术,而且是采用的自己的连接池技术。在 Mybatis 的 mybatis.xml配置文件中,通过来实现 Mybatis 中连接池的配置。MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource。

Mybatis 的数据源分为三类:

UNPOOLED: 不使用连接池的数据源 
POOLED:使用连接池的数据源 
JNDI:使用JNDI实现的数据源 
前两个数据源都实现javax.sql.DataSource接口

7.7 事务

7.7.1、默认是需要手动提交事务的

Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 Connection对象的 commit(), rollback() .Connection 对象的 setAutoCommit()方法来设置事务提交方式的。自动提交和手工提交.

该标签用于指定 MyBatis所使用的事务管理器。MyBatis 支持两种事务管理器类型:JDBC 与 MANAGED。

JDBC:使用JDBC的事务管理机制,通过Connection对象的 commit()方法提交,通过rollback()方法 回滚。默认情况下,mybatis将自动提交功能关闭了,改为了手动提交,观察

日志可以看出,所以我们在程序中都需要自己提交事务或者回滚事务。

7.7.2、自动提交事务—不推荐

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cNkOyCvl-1627200025263)(C:\Users\柳佳宇\AppData\Local\Temp\1621501528535.png)]

SqlSessionFactory的openSession方法由重载,可以设置自动提交的方式。 
如果sqlSession = SqlSessionFactory.openSession(true);参数设置为true,再次执行增删改的时候就不需要执行session.commit()方法,事务会自动提交。

9、Mybatis中的关系映射

9.1 对一关系的映射----共有三种方法

9.1.1 实体类
public class Player { 
    private Integer playerId; 
    private String playerName; 
    private Integer playerNum; 
    private Integer teamId; 
    //多对一的体现:多方持有一方的对象 要有get方法 
    private Team team1;//关联对象--多个球员可以属于同一个球队; 
    //省略set get 和toString方法
9.1.2 mapper接口

以我们在程序中都需要自己提交事务或者回滚事务。

7.7.2、自动提交事务—不推荐

[外链图片转存中…(img-cNkOyCvl-1627200025263)]

SqlSessionFactory的openSession方法由重载,可以设置自动提交的方式。 
如果sqlSession = SqlSessionFactory.openSession(true);参数设置为true,再次执行增删改的时候就不需要执行session.commit()方法,事务会自动提交。

9、Mybatis中的关系映射

9.1 对一关系的映射----共有三种方法

9.1.1 实体类
public class Player { 
    private Integer playerId; 
    private String playerName; 
    private Integer playerNum; 
    private Integer teamId; 
    //多对一的体现:多方持有一方的对象 要有get方法 
    private Team team1;//关联对象--多个球员可以属于同一个球队; 
    //省略set get 和toString方法
9.1.2 mapper接口
9.1.3 对一映射方式1:通过关联对象打点调用属性的方式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值