当前位置: 首页 > news >正文

JavaWeb笔记二

MyBatis

什么是MyBatis?

MyBatis是一种框架,编写的是对数据保存到数据库的代码的框架。

MyBatis快速入门

在这里插入图片描述

创建模块,导入坐标

选择项目结构,添加新模块,然后选择添加maven项目。
接着创建模块。
在这里插入图片描述

在新创建的模块下找到pom.xml文件导入mybatis坐标

注意要导入多个依赖,则都要在dependencies标签里面,否则没有提示信息。

<dependencies>  
<!--        mybatis的依赖-->  <dependency>  <groupId>org.mybatis</groupId>  <artifactId>mybatis</artifactId>  <version>3.5.5</version>  </dependency>  <!--    mysql的依赖-->  <dependency>  <groupId>mysql</groupId>  <artifactId>mysql-connector-java</artifactId>  <version>8.0.29</version>  <scope>test</scope>  </dependency>  </dependencies>

编写mybatis的核心配置文件

作用是用来替换数据库连接信息的

去MyBatis的官网上的快速入门看从XML中构建SqlSessionFactory。

在项目src.main.resources下创建mybatis-config-xml文件。
在这里插入图片描述

mybatis-config-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>  <environments default="development">  <environment id="development">  <transactionManager type="JDBC"/>  <dataSource type="POOLED">  <property name="driver" value="com.mysql.cj.jdbc.Driver"/>  
<!--                连接数据库的信息-->  <property name="url" value="jdbc:mysql://localhost:3306/数据库名字?useSSL=false&amp;serverTimezone=UTC/>  <property name="username" value="用户名"/>  <property name="password" value="密码"/>  </dataSource>        </environment>    </environments>    <mappers>
<!--        加载sql的映射文件-->  <mapper resource="mapper文件的相对路径"/>  <!--    Mapper代理包扫描的方式连接mysql的映射文件-->  <package name="com.itheima.mapper"/></mappers></configuration>
sql映射文件的编写

在项目src.main.resources下创建sql映射文件。统一管理sql语句,解决硬编码问题

文件起名:表名Mapper.xml 例如orderMapper.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="test">  <select id="sql语句的唯一标识" resultType="sql语句对应类的相对路径">  select * from Blog where id = #{id}  </select>  
</mapper>

编写完sql映射文件之后需要在mybatis-config-xml文件里面填写sql映射文件的相对路径。

多行快捷键

alt+鼠标左键

User代码的编写

获取数据库上的数据

//alt+鼠标左键多行编辑  
public class User {  private int  id;  private String  username;  private String  password;  private String  gender;  private String  addr;.......
MyBatisDemo代码的编写

得到sql语句的运行结果

public class MyBatisDemo {  public static void main(String[] args) throws IOException {  //1.加载mybatis配置文件,获取 SqlSessionFactory       String resource = "mybatis-config.xml";//若是直接在resource根目录下,直接写文件名  InputStream inputStream = Resources.getResourceAsStream(resource);  SqlSessionFactory sqlSessionFactory = new            SqlSessionFactoryBuilder().build(inputStream);  //2.获取sqlSession,用他来执行sql  SqlSession sqlSession = sqlSessionFactory.openSession();  //3.执行sql  List<Object> users = sqlSession.selectList("test.selectAll");  //空间名称.sql语句的idSystem.out.println(users);  //4.释放资源  sqlSession.close();  }  
}

执行时遇到这个问题: Exception in thread “main”org.apache.ibatis.exceptions.PersistenceException
跟着下面的链接大佬写的文章解决了。
附上原文链接idea运行mybatis出现Exception in thread “main” org.apache.ibatis.exceptions.PersistenceException等相关问题解决方案-CSDN博客

1.首先关注目录src/main/resources文件夹下的SqlMapConfig.xml文件

如果你的mysql时8.0以上的版本,有两个地方需要修改:

MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL:

com.mysql.cj.jdbc.Driver

jdbc:mysql://localhost:3306/runoob?useSSL=false&serverTimezone=UTC
注意:因为xml文件中,为避免错误的解析,&符号实际用&来表示

URL中的runoob是我自己建立的数据库的名称。

2.关注版本对应问题,这个也是比较难发现的点
将pom.xml文件夹下的mysql-connector-java更换一下版本号至8.0.16

Mapper代理开发(重点)

目的:解决mybatis编写代码中的硬编码问题。

Mapper代理开发的步骤

在这里插入图片描述

步骤一

定义sql的映射文件同名的Mapper接口,并将Mapper接口和sql映射文件置于同一目录下。

在MyBatis框架中,Mapper接口与其对应的XML映射文件的名称通常需要保持一致,但关于大小写问题有以下几点需要注意:

默认匹配规则

  1. 大小写敏感取决于操作系统

    • 在Windows系统上(不区分大小写):UserMapper.java 可以匹配 usermapper.xmlUserMapper.xml

    • 在Linux/Unix系统上(区分大小写):UserMapper.java 必须严格匹配 UserMapper.xml

  2. 最佳实践

    • 建议保持完全一致的大小写,包括首字母大小写

    • 通常采用接口首字母大写,XML文件首字母大写的约定(如UserMapper.javaUserMapper.xml

同一目录下的问题

这个Mapper接口和sql映射文件是在同一目录下,但一般我们会把项目的Java文件和配置文件分开,因此这种方式不推荐。
在这里插入图片描述

可以在resources文件夹下创建与mapper接口相同的目录结构,项目编译之后,mapper接口和sql映射文件也会在同一目录下。

编译之后的字节码文件的结构只有java文件夹下的文件结构及编译之后的字节码文件和配置文件,其中配置文件若是在跟Java目录结构相同的情况下,那么在那个文件下面也有该配置文件,如下下图所示
在这里插入图片描述
在这里插入图片描述

在resources文件下创建目录不能用点,如下图所示
在这里插入图片描述

正确做法如下图
在这里插入图片描述

步骤二

设置sql映射文件的namespace属性为Mapper接口全限定名
在这里插入图片描述

步骤三

在Mapper接口中定义方法,方法名就是sql映射文件中sql语句的id,并保持参数类型和返回值一致。
在这里插入图片描述

注意上面该条语句是查询所有的数据那么返回的应该是一个User的集合类型。

最后因为改变了连接mysql的映射文件userMapper.xml的路径因此需要在mybatis-config.xml修改该路径。
在这里插入图片描述

<!--    Mapper代理包扫描的方式连接mysql的映射文件-->  <package name="com.itheima.mapper"/>

步骤四

编码
在这里插入图片描述

//3.1获取userMapper接口的代理对象  
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);  
List<User> users = userMapper.selectAll();  
System.out.println(users);
小细节

在这里插入图片描述

在这里插入图片描述

MyBatis配置文件

mybatis配置文件里面件包含了会深深影响 MyBatis 行为的设置和属性信息。

配置文档的顶层结构

配置文档的顶层结构如下:

在这里插入图片描述

环境配置(environments)

可以将sql映射到不同的数据库中。

映射器(mappers)

目的:解决mybatis编写代码中的硬编码问题。

类型别名(typeAliases)

可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases><package name="domain.blog"/>
</typeAliases>

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author.

在配置各个标签的时候,需要遵守前后顺序。

对数据库数据完成增删改查(重点)

配置文件完成增删改查

在这里插入图片描述

练习

前置步骤
数据库表
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(-- id 主键id           int primary key auto_increment,-- 品牌名称brand_name   varchar(20),-- 企业名称company_name varchar(20),-- 排序字段ordered      int,-- 描述信息description  varchar(100),-- 状态:0:禁用  1:启用status       int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),('小米', '小米科技有限公司', 50, 'are you ok', 1);SELECT * FROM tb_brand;
实体类 Brand
package com.itheima.pojo;  /**  * 品牌  *  * alt + 鼠标左键:整列编辑  *  * 在实体类中,基本数据类型建议使用其对应的包装类型  */  public class Brand {  // id 主键  private Integer id;  // 品牌名称  private String brandName;  // 企业名称  private String companyName;  // 排序字段  private Integer ordered;  // 描述信息  private String description;  // 状态:0:禁用  1:启用  private Integer status;  public Integer getId() {  return id;  }  public void setId(Integer id) {  this.id = id;  }  public String getBrandName() {  return brandName;  }  public void setBrandName(String brandName) {  this.brandName = brandName;  }  public String getCompanyName() {  return companyName;  }  public void setCompanyName(String companyName) {  this.companyName = companyName;  }  public Integer getOrdered() {  return ordered;  }  public void setOrdered(Integer ordered) {  this.ordered = ordered;  }  public String getDescription() {  return description;  }  public void setDescription(String description) {  this.description = description;  }  public Integer getStatus() {  return status;  }  public void setStatus(Integer status) {  this.status = status;  }  @Override  public String toString() {  return "Brand{" +  "id=" + id +  ", brandName='" + brandName + '\'' +  ", companyName='" + companyName + '\'' +  ", ordered=" + ordered +  ", description='" + description + '\'' +  ", status=" + status +  '}';  }  
}
测试用例MyBatisTest

在这里插入图片描述

MyBatisX插件

提高开发效率

增删改查

在这里插入图片描述

最主要的三件事

sql语句怎么写?
完成某个功能要不要参数
完成之后返回怎样的结果

查询所有数据
MyBatisTest代码
public class MyBatisTest {  @Test  public void testSelectAll() throws IOException {  //1.加载mybatis配置文件,获取 SqlSessionFactory       String resource = "mybatis-config.xml";//若是直接在resource根目录下,直接写文件名  InputStream inputStream = Resources.getResourceAsStream(resource);  SqlSessionFactory sqlSessionFactory = new         SqlSessionFactoryBuilder().build(inputStream);  //2.获取sqlSession,用他来执行sql  SqlSession sqlSession = sqlSessionFactory.openSession();  //3.获取Mapper代理对象  BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);  //4.执行方法  List<Brand> list = mapper.selectAll();  System.out.println(list);  //5.释放资源  sqlSession.close();  }  }
代码执行之后,返回的数据有的字段为null的解决方式

造成这种的原因是,sql片段#{}里面的数据名称与类的属性名不一样

在xxMapper.xml文件下编写修改下列代码
在这里插入图片描述

<!--namespace:名称空间-->  
<mapper namespace="com.itheima.mapper.BrandMapper">  <resultMap id="brandResultMap" type="brand">  
<!--        id 唯一标识    result 完成一般字段的映射  column:数据库字段名   property:java变量名  
-->  <result column="brand_name" property="brandName"/>  <result column="company_name" property="companyName"/>  </resultMap>    <select id="selectAll" resultMap="brandResultMap">  select * from tb_brand;  </select>  
</mapper>
查看详情

在这里插入图片描述

<select id="selectById" parameterType="int" resultMap="brandResultMap">  //其中参数可以省略select * from tb_brand where id=#{id};  
</select>
参数占位符的问题

*参数占位符
1.#{}:会将其替换为?为了防止sql注入
2.KaTeX parse error: Expected 'EOF', got '#' at position 42: … 1.参数传递时:#̲{} (常用) …{}

特殊字符问题

例如:select * from tb_brand where id<#{id};会报错,因为在xml文件下<是标签

解决方式:
1.转义字符
select * from tb_brand where id < #{id} //其中<是<的转义字符
2.CDATA区

	select * from tb_brand where id  <![CDATA[ 内容 ]]> #{id};
总结

在这里插入图片描述

条件查询(重要)
多条件查询

在这里插入图片描述

多条件查询接口参数编写的方法
在这里插入图片描述

方法一:为每个参数标上注解,注解里面的内容要和对应的sql语句里面占位符里面的内容一样。

List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);//int status传递给Param里面的status的占位符

方法二:若传递的参数属于同一个对象,那么可以封装成一个对象,把对象传递到方法里面来。占位符里面的名称要和对象属性里的名称一样,不然找不到。

BrandMapper里面的核心代码
List<Brand> selectByCondition(Brand brand);Test里面的核心代码
//处理参数  
companyName="%"+companyName+"%";  
brandName="%"+brandName+"%";//封装对象  
Brand brand = new Brand();  
brand.setStatus(status);  
brand.setCompanyName(companyName);  
brand.setBrandName(brandName);//执行方法
List<Brand> brands = mapper.selectByCondition(brand);

方法三:把参数封装成map,map集合键的名称要和三个参数占位符名称保持一致。

BrandMapper里面的核心代码
List<Brand> selectByCondition(Map map);Test里面的核心代码
//Map对象  
Map map=new HashMap();  
map.put("status",status);  
map.put("companyName",companyName);  
map.put("brandName",brandName);
//执行方法
List<Brand> brands = mapper.selectByCondition(map);
多条件动态条件查询

编写动态sql语句来实现动态条件查询,解决用户只输入了一个条件查询的问题。
在这里插入图片描述

BrandMapper.xml核心代码<select id="selectByCondition" resultMap="brandResultMap">  select  *   from tb_brand    <where>  <if test="status!=null">  status=#{status}  </if>  <if test="companyName!=null and companyName!=' ' ">  and  company_name like #{companyName}  </if>  <if test="brandName!=null and brandName!=' ' ">  and brand_name like #{brandName};  </if>  </where>  
</select>
单条件动态条件查询

在这里插入图片描述

BrandMapper.xml核心代码
<select id="selectByConditionSingle" resultMap="brandResultMap">  select * from tb_brand  <where>  <choose>  <when test="status!=null">  status=#{status}  </when>  <when test="companyName!=null and companyName!=' ' ">  company_name like #{companyName}  </when>  <when test="brandName!=null and brandName!=' '">  brand_name like #{brandName};  </when>  <otherwise>  1=1  </otherwise>  </choose>  </where>  
</select>

注解完成增删改查

添加数据

在这里插入图片描述

BrandMapper.xml核心代码
<insert id="add">  insert into tb_brand(brand_name, company_name, ordered, description, status) value (#{brandName},#{companyName},#{ordered},#{description},#{status});  
</insert>
Test核心代码//2.获取sqlSession,用他来执行sql  
SqlSession sqlSession = sqlSessionFactory.openSession(true);//注意这里要设置为true//4.执行方法  
Brand brand = new Brand();  
//获取参数  
String brandName="小舞手机";  
String companyName="凤凰集团";  
int ordered=100000;  
String description="渣成的小舞手机";  
int status = 1;  
brand.setStatus(status);  
brand.setCompanyName(companyName);  
brand.setBrandName(brandName);  
brand.setOrdered(ordered);  
brand.setDescription(description);  
mapper.add(brand);
返回添加数据的主键

在这里插入图片描述

BrandMapper.xml核心代码
<insert id="add" useGeneratedKeys="true" keyProperty="id">
Test核心代码
Integer id = brand.getId();  
System.out.println(id);

修改全部字段

在这里插入图片描述

BrandMapper.xml核心代码
<update id="update">  update  tb_brand    set        brand_name=#{brandName},        company_name=#{companyName},        ordered=#{ordered},        description=#{description},        status=#{status}    where        id=#{id};</update>
Test核心代码
Brand brand = new Brand();  
//获取参数  
String brandName="江南会所";  
String companyName="凤凰集团";  
int ordered=100000;  
String description="颜麝的风华绝代";  
int status = 1;  
int id=1;  
brand.setStatus(status);  
brand.setCompanyName(companyName);  
brand.setBrandName(brandName);  
brand.setOrdered(ordered);  
brand.setDescription(description);  
brand.setId(id);  
int update = mapper.update(brand);  
System.out.println(update);

修改动态字段

在这里插入图片描述

BrandMapper.xml核心代码
<update id="updateMove">  update  tb_brand    <set>  <if test="brandName!=null and brandName!=''">  brand_name=#{brandName},  </if>  <if test="companyName!=null and companyName!=''">  company_name=#{companyName},  </if>  <if test="ordered!=null">  ordered=#{ordered},  </if>  <if test="description!=null and description!=''">  description=#{description},  </if>  <if test="status!=null">  status=#{status}  </if>  </set>  where  id=#{id};</update>

删除一个

在这里插入图片描述

BrandMapper.xml核心代码
<delete id="delete">  delete  from tb_brand where id=#{id};  
</delete>

删除多个

在这里插入图片描述

mybatis会将数组参数封装成一个Map集合
默认是:array=数组
使用@Param注解改变map集合默认的key的名称

BrandMapper.java核心代码
void deleteByIds(@Param("ids") int[] ids);
BrandMapper.xml核心代码
<delete id="deleteByIds">  delete  from tb_brand where id in  <foreach collection="ids" item="id" separator="," open="(" close=")">  #{id}  </foreach>  
</delete>

或者

BrandMapper.java核心代码
void deleteByIds(int[] ids);
BrandMapper.xml核心代码
<delete id="deleteByIds">  delete  from tb_brand where id in  <foreach collection="array" item="id" separator="," open="(" close=")">  #{id}  </foreach>  
</delete>

MyBatis参数传递

多个参数

封装为Map集合,使用@Param注解,替换Map集合中默认的arg键名。Param(“这里名字要和sql语句里#{}里面的一样”)

单个参数

在这里插入图片描述

注解

在这里插入图片描述

http://www.xdnf.cn/news/1100179.html

相关文章:

  • 企业级配置:Azure 邮件与 Cloudflare 域名解析的安全验证落地详解
  • CReFT-CAD 笔记 带标注工程图dxf,png数据集
  • JVM 内存结构
  • 每天一个前端小知识 Day 29 - WebGL / WebGPU 数据可视化引擎设计与实践
  • 人工智能-基础篇-29-什么是低代码平台?
  • AI问答之手机相机专业拍照模式的主要几个参数解释
  • 人工智能-基础篇-28-模型上下文协议--MCP请求示例(JSON格式,客户端代码,服务端代码等示例)
  • 大数据学习7:Azkaban调度器
  • 《Effective Python》第十三章 测试与调试——使用 Mock 测试具有复杂依赖的代码
  • Three.js+Shader实现三维波动粒子幕特效
  • 量子计算系统软件:让“脆弱”的量子计算机真正可用
  • DDL期间TDSQL异常会话查询造成数据库主备切换
  • 【NLP入门系列六】Word2Vec模型简介,与以《人民的名义》小说原文实践
  • 如何利用个人电脑搭建数据库服务器实现远程协作
  • RabbitMQ用法的6种核心模式全面解析
  • 零基础入门物联网-远程门禁开关:云平台创建
  • 自动驾驶控制系统
  • 李宏毅(深度学习)--(2)
  • 【TCP/IP】10. 引导协议与动态主机配置协议
  • 查看uniapp 项目中没有用到依赖
  • mx6ull-裸机学习实验15——RTC 实时时钟实验
  • 【养老机器人】核心技术
  • 栈题解——有效的括号【LeetCode】两种方法
  • LangChain框架 Prompts、Agents 应用
  • Git 学习笔记
  • OpenAI正准备推出一款搭载人工智能功能的网络浏览器,试图直接挑战Alphabet旗下
  • RISC-V:开源芯浪潮下的技术突围与职业新赛道 (二) RISC-V架构深度解剖(上)
  • 链表算法之【合并两个有序链表】
  • 【算法笔记 day three】滑动窗口(其他类型)
  • STM32第十九天 ESP8266-01S和电脑实现串口通信(2)