MyBatis完成CRUD 具体细节内容

打印 上一主题 下一主题

主题 886|帖子 886|积分 2658

1. MyBatis完成CRUD 具体细节内容

@
目录

每博一文案
  1. 书再难背,也就几个月,跑步再累也就五分钟,题目再难,
  2. 也会有解法,累了就听听歌,散散步,出去走走。所以,你不会
  3. 且觉得难的东西一定不要躲,先弄明白,后精湛,你就比别人优秀。
  4.                                 ——————《罗翔老师》
复制代码
2. MyBatis工具类SqlSessionUtil的封装

我们可以先将 SqlSession 对象的获取,封装成一个工具类来使用,方便一些。关于 SqlSession 对象的获取的具体内容,大家可以移步至:✏️✏️✏️ 初始MyBatis ,具体步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层分析-CSDN博客

一般我们的工具类,的构造方法都是私有化的,防止 new 对象。

工具类中所以的方法都是静态的,直接用 类名.方法名 的方式直接调用

获取到SqlSessionFactory 对象
SQlsessionFactory对象,一个SqlSessionFactory对应一个 environment, 一个environment通常是一个数据库。所以,我们定义一个静态代码块,执行加载一次即可。
  1. package com.rainbowsea.mybatis.utils;
  2. import org.apache.ibatis.io.Resources;
  3. import org.apache.ibatis.session.SqlSession;
  4. import org.apache.ibatis.session.SqlSessionFactory;
  5. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  6. import java.io.IOException;
  7. public class SqlSessionUtil {
  8.     // 工具类的构造方法一般都是私有话化的
  9.     // 工具类中所有的方法都是静态的,直接类名即可调用,不需要 new 对象
  10.     // 为了防止new对象,构造方法私有化。
  11.     private SqlSessionUtil() {
  12.     }
  13.     private static SqlSessionFactory sessionFactory = null;
  14.     // 静态代码块,类加载时执行
  15.     // SqlSessionUtil 工具类在进行第一次加载的时候,解析mybatis-config.xml 文件,创建SqlSessionFactory对象。
  16.     static {
  17.         // 获取到  SqlSessionFactoryBuilder 对象
  18.         SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
  19.         // 获取到SqlSessionFactory 对象
  20.         // SQlsessionFactory对象,一个SqlSessionFactory对应一个 environment, 一个environment通常是一个数据库
  21.         try {
  22.             sessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
  23.         } catch (IOException e) {
  24.             throw new RuntimeException(e);
  25.         }
  26.     }
  27.     /**
  28.      * 获取会话对象
  29.      * @return SqlSession
  30.      */
  31.     public static SqlSession openSession() {
  32.         // 获取到 SqlSession 对象
  33.         SqlSession sqlSession = sessionFactory.openSession();
  34.         return sqlSession;
  35.     }
  36. }
复制代码
3. 预备工作

首先我们预备操作,实验的数据库,数据表。数据内容


在项目/模块当中导入相关的 jar 依靠,在pom.xml 配置相关 jar依靠的。
我们需要的依靠有:


  • mybatis依靠
  • mysql驱动依靠
  • junit依靠
  • logback依靠
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5.     <modelVersion>4.0.0</modelVersion>
  6.     <groupId>com.rainbowsea</groupId>
  7.     <artifactId>mybatis-002-crud</artifactId>
  8.     <version>1.0-SNAPSHOT</version>
  9.     <packaging>jar</packaging>
  10.     <properties>
  11.         <maven.compiler.source>17</maven.compiler.source>
  12.         <maven.compiler.target>17</maven.compiler.target>
  13.     </properties>
  14.     <dependencies>
  15.         <dependency>
  16.             <groupId>org.mybatis</groupId>
  17.             <artifactId>mybatis</artifactId>
  18.             <version>3.5.10</version>
  19.         </dependency>
  20.         <dependency>
  21.             <groupId>mysql</groupId>
  22.             <artifactId>mysql-connector-java</artifactId>
  23.             <version>8.0.30</version>
  24.         </dependency>
  25.         <dependency>
  26.             <groupId>junit</groupId>
  27.             <artifactId>junit</artifactId>
  28.             <version>4.13.2</version>
  29.             <scope>test</scope>
  30.         </dependency>
  31.         
  32.         <dependency>
  33.             <groupId>ch.qos.logback</groupId>
  34.             <artifactId>logback-classic</artifactId>
  35.             <version>1.2.11</version>
  36.         </dependency>
  37.     </dependencies>
  38. </project>
复制代码
其次就是:


  • mybatis-config.xml放在类的根路径下
  • CarMapper.xml放在类的根路径下
  • logback.xml放在类的根路径下
  • 提供com.powernode.mybatis.utils.SqlSessionUtil工具类
  • 创建测试用例:com.powernode.mybatis.CarMapperTest
上述内容,为什么放在类的根路径下(resources) 就是为了提高项目的可移植性。具体内容,大家可以移步至:✏️✏️✏️  初始MyBatis ,具体步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层分析-CSDN博客


  • mybatis-config.xml放在类的根路径下
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3.         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6.    
  7.    
  8.    
  9.    
  10.    
  11.     <environments default="development">
  12.         <environment id="development">
  13.             
  14.             <transactionManager type="JDBC"/>
  15.             <dataSource type="POOLED">
  16.                 <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
  17.                 <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
  18.                 <property name="username" value="root"/>
  19.                 <property name="password" value="MySQL123"/>
  20.             </dataSource>
  21.         </environment>
  22.     </environments>
  23.     <mappers>
  24.         
  25.         
  26.         
  27.         
  28.         
  29.         
  30.         
  31.         
  32.         <mapper resource="CarMapper.xml"></mapper>
  33.     </mappers>
  34. </configuration>
复制代码
同时需要配置 MyBatis 的核心配置文件,告诉 MyBatis 要使用哪个 XxxMapper .xml SQL 语句的映射文件。


  • CarMapper.xml放在类的根路径下
  1. [/code]
  2. [list]
  3. [*]logback.xml放在类的根路径下
  4. [/list][align=center][img]https://img2024.cnblogs.com/blog/3084824/202405/3084824-20240530113623270-844844870.png[/img][/align]
  5. [code]<?xml version="1.0" encoding="UTF-8"?>
  6. <configuration debug="false">
  7.    
  8.     <appender name="STDOUT" >
  9.         <encoder >
  10.             
  11.             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
  12.         </encoder>
  13.     </appender>
  14.    
  15.     <logger name="com.apache.ibatis" level="TRACE"/>
  16.     <logger name="java.sql.Connection" level="DEBUG"/>
  17.     <logger name="java.sql.Statement" level="DEBUG"/>
  18.     <logger name="java.sql.PreparedStatement" level="DEBUG"/>
  19.    
  20.     <root level="DEBUG">
  21.         <appender-ref ref="STDOUT"/>
  22.         <appender-ref ref="FILE"/>
  23.     </root>
  24. </configuration>
复制代码
3.1 insert 添加/插入记录

分析以下SQL映射文件中SQL语句存在的问题
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="car">
  6.     <insert id="insertCar">
  7.         insert into t_car(car_num,brand,guide_price,produce_time,car_type) values('103', '奔驰E300L', 50.3, '2022-01-01', '燃油车')
  8.     </insert>
  9. </mapper>
复制代码

这样写的问题是:
值,显然是写死到配置文件当中了
这个实际开发中是不存在的
肯定是前端 form 表单提交过来数据,然后将值传给 sql 语句
SQL语句中的值不应该写死,值应该是用户提供的。之前的JDBC代码是这样写的:
  1. // JDBC中使用 ? 作为占位符。那么MyBatis中会使用什么作为占位符呢?
  2. String sql = "insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(?,?,?,?,?)";
  3. // ......
  4. // 给 ? 传值。那么MyBatis中应该怎么传值呢?
  5. ps.setString(1,"103");
  6. ps.setString(2,"奔驰E300L");
  7. ps.setDouble(3,50.3);
  8. ps.setString(4,"2022-01-01");
  9. ps.setString(5,"燃油车");
复制代码
在JDBC当中占位符采用的是?,在mybatis当中是什么呢?
  1. 和?等效的写法是: #{}
复制代码
在mybatis当中不能使用 ? 占位符,必须使用 #{ } 来代替JDBC当中的  ?
#{ }  和JDBC当中的 ? 是等效的。
在MyBatis 中,的Java程序中,将数据放到Map集合中
在sql语句中使用 #{map集合的key} 来完成传值,#{} 等同于JDBC中的 ? ,#{}就是占位符
我们在 XxxMapper.xml SQL 映射文件当中,使用上 #{ } 重新编写 对于的 insert SQL 语句

这里的 id 是作为主键的,自增的,可以省略不写。
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.                 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.                 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="rainbowsea">
  6.         <insert id="insertCar">
  7.                 insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
  8.                 values (null,#{k1},#{k2},#{k3},#{k4},#{k5})
  9.         </insert>
  10. </mapper>
复制代码
在MyBatis 中的Java程序中使用 map 可以给SQL语句的占位符传值。
Map map = new HashMap();
  1. map.put("k1","111");
  2. map.put("k2","比亚迪汉");
  3. map.put("k3",10.0);
  4. map.put("k4","2020-11-11");
  5. map.put("k5","电车");
复制代码
添加/插入,执行 sqlSession.insert("Id", car); 方法

这里执行 **insert( ) ** 插入操作,则是用:sqlSession.insert(String var1, Object var2); 两个参数的方法,执行 insert() 插入操作,返回影响的记录条数。
  1. // 执行sql语句
  2. // insert方法的参数:
  3. // 第一个参数:sqlId;从CarMapper.xml 文件中复制,的对于是insert SQL 语句的 id 信息
  4. // 第二个参数: 封装数据的对象,这里为 Map 集合
  5. int count = sqlSession.insert("insertCar", map);
复制代码
  1. insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values (null,#{fdsd},#{k2},#{k3},#{k4},#{k5})
  2. 注意:#{这里写什么?写map集合的key,如果key不存在,获取的是null}
复制代码
运行测试:

在以上sql语句中,可以看到#{k1} #{k2} #{k3} #{k4} #{k5}的可读性太差,为了增强可读性,我们可以将Java程序做如下修改:

对应的 CarMapper.xml SQL映射文件也是要逐一对应修改。

运行测试:

insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values (null,#{fdsd},#{k2},#{k3},#{k4},#{k5})
留意:#{这里写什么?写map集合的key,如果key不存在,获取的是null}。如下:我们测试

使用Map集合可以传参,那使用pojo(简朴普通的java对象)可以完成传参。
java 程序中使用POJO类给SQL语句的占位符传值。
这里我们定义一个 名为 Car.java 的类,该类要与t_car 数据表的属性,像映射,对应上的。不可以随便定义的。

同时我们将属性定义为包装类,防止当我们数据表当中取出,获取到的数据是为 null 的时候,包装类可以赋值上,而简朴类型 int 是无法赋值为 Null 的

同时肯定要提供对应的 set 和 get 方法,不然 ,MyBatis 无法通过反射机制获取到相应所需要的信息的。
  1. package com.rainbowsea.mybatis.pojo;
  2. public class Car {
  3.     //数据表当中的字段应该和pojo类的属性一一对应
  4.     // 建议使用包装类,这样可以防止 null 的问题:int = null; 不行,Int = null 可以
  5.     private Long id;
  6.     private String carNum;
  7.     private String brand;
  8.     private Double guiderPrice;
  9.     private String produceTime;
  10.     private String carType;
  11.     public Car() {
  12.     }
  13.     public Car(Long id, String carNum, String brand, Double guiderPrice, String produceTime, String carType) {
  14.         this.id = id;
  15.         this.carNum = carNum;
  16.         this.brand = brand;
  17.         this.guiderPrice = guiderPrice;
  18.         this.produceTime = produceTime;
  19.         this.carType = carType;
  20.     }
  21.     @Override
  22.     public String toString() {
  23.         return "Car{" +
  24.                 "id=" + id +
  25.                 ", carNum='" + carNum + '\'' +
  26.                 ", brand='" + brand + '\'' +
  27.                 ", guiderPrice=" + guiderPrice +
  28.                 ", produceTime='" + produceTime + '\'' +
  29.                 ", carType='" + carType + '\'' +
  30.                 '}';
  31.     }
  32.     public Long getId() {
  33.         return id;
  34.     }
  35.     public void setId(Long id) {
  36.         this.id = id;
  37.     }
  38.     public String getCarNum() {
  39.         return carNum;
  40.     }
  41. /*    public String getXyz() {
  42.         return carNum;
  43.     }*/
  44.     public void setCarNum(String carNum) {
  45.         this.carNum = carNum;
  46.     }
  47.     public String getBrand() {
  48.         return brand;
  49.     }
  50.     public void setBrand(String brand) {
  51.         this.brand = brand;
  52.     }
  53.     public Double getGuiderPrice() {
  54.         return guiderPrice;
  55.     }
  56.     public void setGuiderPrice(Double guiderPrice) {
  57.         this.guiderPrice = guiderPrice;
  58.     }
  59.     public String getProduceTime() {
  60.         return produceTime;
  61.     }
  62.     public void setProduceTime(String produceTime) {
  63.         this.produceTime = produceTime;
  64.     }
  65.     public String getCarType() {
  66.         return carType;
  67.     }
  68.     public void setCarType(String carType) {
  69.         this.carType = carType;
  70.     }
  71. }
复制代码
java 程序中使用POJO类给SQL语句的占位符传值:
// 封装数据
Car car = new Car(null, "333", "比亚迪泰", 30.0, "2020-11-11", "新能源");
留意:占位符#{ }, 大括号内里写:pojo类的属性名
insert into t_car(id,car_num,bread,guider_prive,produce_time,car_type)
values(null,#{xyz},#{brand},#{guiderPrice},#{produceTime},#{carType})

运行测试:
  1. public void testInsertCarByPOJO() {
  2.         SqlSession sqlSession = SqlSessionUtil.openSession();
  3.         // 封装数据
  4.         Car car = new Car(null, "333", "比亚迪泰", 30.0, "2020-11-11", "新能源");
  5.         // 执行SQL
  6.         int count = sqlSession.insert("insertCar", car); // ORM       // 对应XxxMapper.xml 上的id
  7.         System.out.println(count);
  8.         sqlSession.commit();
  9.         sqlSession.close();
  10.     }
复制代码

如果我们在 XxxMapper.xml(这里是CarMapper.xml) 的SQL映射文件中 的  标签 中的 #{ } 占位符,写的不是对应pojo(这里是 Car) 类上的属性值时,会出现什么问题,是报错,还是赋值为 Null呢?

运行测试:

报错信息:
There is no getter for property named 'xyz' in 'class com.rainbowsea.mybatis.pojo.Car'
mybatis 去找,Car类中的getXyz()方法去了,没找到,报错了。
怎么解决的?
我们在pojo(这里是 Car) 类当中参加一个 getXyz( ) 方法,方法的返回值和 原来的getCarNum( )的返回值,一样就是,方法名不同而已:就是方法名不同,返回的值还是:carNum

再运行测试;

通过这个测试,得出一个结论:
严格意义上来说,如果使用POJO对象通报值的话,#{}这个大括号中i给你到底写什么?
写的是对应的属性的 get方法的方法名去掉 get,然后将剩下的单词字母小写,然后放进去。
例如:getUsername() ---> #{username}
例如: getEmail() ---> #{email}
也就是说MyBatis在底层,传值的时候,先要获取值,怎么获取的?
调用了pojo对象的get方法,例如:car.getCarNum(); car.getCarType(), car.getBreand() 方法
经过测试得出结论:
如果采用map集合传参,#{} 里写的是map集合的key,如果key不存在不会报错,数据库表中会插入NULL。
如果采用POJO传参,#{} 里写的是get方法的方法名去掉get之后将剩下的单词首字母变小写(例如:getAge对应的是#{age},getUserName对应的是#{userName}),如果这样的get方法不存在会报错。
留意:实在传参数的时候有一个属性 parameterType,这个属性用来指定传参的数据类型,不外这个属性是可以省略的

3.2 delete 删除记录

需求:根据 id 删除数据,将 id = 44 的数据删除。
编写XxxMapper.xml SQL 映射的文件, 删除用  标签
  1.         <delete id="deleteById">
  2.                 delete from t_car where id = #{id}
  3.         </delete>
复制代码
留意:当占位符只有一个的时候,#{} 内里的内容可以随便写。
只有一个占位符的时候,传一个值,MyBatis 可以自动载入,但是 #{} 不可以空着,要写上值
运行测试:
Java程序执行,删除操作,用sqlSession.delete("Id", 值) 方法,删除记录

  1. @Test
  2.     public void testDeleteById() {
  3.         SqlSession sqlSession = SqlSessionUtil.openSession();
  4.         // 执行SQL语句
  5.         sqlSession.delete("deleteById",44); // 如果只要一个值的时候,就不需要对应上的的 Object 类型了
  6.         sqlSession.commit(); // 提交
  7.         sqlSession.close(); // 关闭
  8.     }
复制代码

3.3 update 修改记录

需求: 根据 id 修改某条记录
需求:修改 id=46 的Car信息,car_num为999,brand为凯美瑞,guide_price为30.00,produce_time为2020-011-11,car_type为燃油车。
编写XxxMapper.xml SQL 映射的文件,修改用  标签
  1.         <update id="updateById">
  2.                 update t_car set car_num = #{carNum}, brand=#{brand}, guide_price=#{guiderPrice},produce_time=#{produceTime},
  3.                                  car_type=#{carType} where id =#{id}
  4.         </update>
复制代码
运行测试:
Java程序执行,修改/更新数据操作,用sqlSession.update("Id", 值) 方法,修改记录



  1.    public void testUpdateById() {
  2.         SqlSession sqlSession = SqlSessionUtil.openSession();
  3.         Car car = new Car(46L, "999", "凯美瑞", 30.3, "1999-11-10", "燃油车");
  4.         // 执行SQL语句
  5.         int count = sqlSession.update("updateById", car);
  6.         System.out.println(count);
  7.         sqlSession.commit();
  8.         sqlSession.close();
  9.     }
复制代码
当然了,如果使用 map传数据也是可以的。
3.4 select 查询记录

3.4.5 select 查询一条记录

select语句和其它语句不同的是:查询会有一个结果集。
需求:根据id 查询对应的一条记录,这里我们查询 id = 1 的记录信息。
在XxxMapper.xml 文件当中编写,对应的查询语句,查询用  标签。

运行测试:
因为查询,没有修改的操作,是不需要事务操作的,所以我们不同提交数据,给数据库。
这里我们查询的是一条记录,用 sqlSession.selectOne("id")  方法,返回一个 映射对象。



报错信息:Error querying database.  Cause: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement 'rainbowsea.selectById'.  It's likely that neither a Result Type nor a Result Map was specified.
以上的异常大致的意思是:对于一个查询语句来说,你需要指定它的“结果类型”或者“结果映射”。
所以说,你想让mybatis查询之后返回一个Java对象的话,至少你要告诉mybatis返回一个什么类型的Java对象,可以在标签中添加 resultType 属性,所赋值的对象是:全限定类名 ,用来指定查询要转换的类型:
需要特别留意的是:
select 标签中给的resultType属性,这个属性用来告诉mybatis,查询结果封装什么类型的Java对象
resultType通常写的是:全限定类名
  1.         <select id="selectById" resultType="com.rainbowsea.mybatis.pojo.Car">
  2.                 select id,car_num as carNum, brand, guide_price as guiderPrice,
  3.                 produce_time as produceTime,
  4.                 car_type as carType
  5.                 from t_car
  6.                 where id= #{id}
  7.         </select>
复制代码
我们再次运行:

运行后之前的异常不再出现了,这说明添加了resultType属性之后,解决了之前的异常,可以看出resultType是不能省略的。
仔细观察控制台的日记信息,不丢脸出,结果查询出了一条。而且每个字段都查询的到值了:

但是奇怪的是返回的Car对象,只有 id 和 brand 两个属性有值,其它属性的值都是 null,

这是为什么呢?我们来观察一下查询结果列名和Car类的属性名是否能逐一对应:

通过观察发现:只有 id 和 brand 是同等的,其他字段名和属性名对应不上,这就是导致null的原因了?我们可以在sql语句中使用 as 关键字来给查询结果列名起别名的方式,让它们两者保持同等的关系。

  1.         <select id="selectById" resultType="com.rainbowsea.mybatis.pojo.Car">
  2.                 select id,car_num as carNum, brand, guide_price as guiderPrice,
  3.                 produce_time as produceTime,
  4.                 car_type as carType
  5.                 from t_car
  6.                 where id= #{id}
  7.         </select>
复制代码

3.4.6 select 查询多条记录

需求:查询全部的Car信息。
编写对应的SQL语句,在 XxxMapper.xml SQl语句映射文件当中。
同样我们需要使用上 as 关键字,定义别名,使其Java程序和数据库的字段名两者之间的字段保持同等。
  1.         <select id="selectAll" resultType="com.rainbowsea.mybatis.pojo.Car">
  2.                 select
  3.                        id,car_num as carNum, brand, guide_price as guiderPrice,
  4.                            produce_time as produceTime,
  5.                            car_type as carType
  6.                 from
  7.                        t_car
  8.         </select>
复制代码
Java代码如下:
这里,因为我们查询的是多条记录,用 sqlSession.selectList("id")  方法,返回一个 List 集合,存储着我们的查询结果集

如果是返回的是键值对 的话,我们还可以用 sqlSession.selectMap("id") 方法 返回的是一个 Map 集合

运行结果:
  1.    <select id="selectAll" resultType="com.rainbowsea.mybatis.pojo.Car">
  2.       select
  3.              id,car_num as carNum, brand, guide_price as guiderPrice,
  4.             produce_time as produceTime,
  5.             car_type as carType
  6.       from
  7.              t_car
  8.    </select>
  9.   List<Car> cars = sqlSession.selectList("selectAll");
  10. 注意: resultType 还是指定封装的结果集的类型,不是指定List类型,是指定List集合中元素的类型
  11. selectList 方法,mybatis通过这个方法就可以得知你需要一个List集合,它会自动给你返回一个List集合
复制代码
4. 关于SQL  Mapper 的 namespace 的使用方式

在SQL Mapper配置文件中  标签的 namespace 属性可以翻译为定名空间,这个定名空间主要是为了防止sqlId冲突的。

我们在创建一个 UserMapper.xml 的SQL 语句的映射文件,同样将其 namespace = "rainbowsa" 这个值,同时两个配置文件当中都有同一个:select 查询语句,同时 id 都为 selectAll 。运行看看,存在什么问题?
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.                 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.                 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="rainbowsea">
  6.         <select id="selectAll" resultType="com.rainbowsea.mybatis.pojo.Car">
  7.                 select
  8.                         id,car_num as carNum, brand, guide_price as guiderPrice,
  9.                         produce_time as produceTime,
  10.                         car_type as carType
  11.                 from
  12.                         t_car
  13.         </select>
  14. </mapper>
复制代码
将它们都配置到:将CarMapper.xml 和  UserMapper.xml 都配置到mybatis-config.xml文件中。
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3.         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6.    
  7.    
  8.    
  9.    
  10.    
  11.     <environments default="development">
  12.         <environment id="development">
  13.             
  14.             <transactionManager type="JDBC"/>
  15.             <dataSource type="POOLED">
  16.                 <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
  17.                 <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
  18.                 <property name="username" value="root"/>
  19.                 <property name="password" value="MySQL123"/>
  20.             </dataSource>
  21.         </environment>
  22.     </environments>
  23.     <mappers>
  24.         
  25.         
  26.         
  27.         
  28.         
  29.         
  30.         
  31.         
  32.         <mapper resource="CarMapper.xml"></mapper>
  33.     </mappers>
  34. </configuration>        
复制代码
编写Java代码如下:
  1. public void testNamespace() {
  2.         SqlSession sqlSession = SqlSessionUtil.openSession();
  3.         // 执行SQL语句
  4.         // 正确的完整写法:namespace.id
  5.         List<Car> cars = sqlSession.selectList("selectAll");
  6.         // 遍历
  7.         cars.forEach(car -> {
  8.             System.out.println(car);
  9.         });
  10.         //sqlSession.commit();  查询不用提交,没有事务问题
  11.         sqlSession.close();
  12.     }
复制代码
运行报错:

Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'UserMapper.xml'. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for rainbowsea.selectAll. please check CarMapper.xml and UserMapper.xml
【翻译】selectCarAll在Mapped Statements集合中不明确(请实验使用包含名称空间的全名,或重定名其中一个条目)
【大致意思是】selectCarAll重名了,你要么在selectCarAll前添加一个名称空间,要有你改个其它名字。
这里我们修改一下 UserMapper.xml 文件当中的 namespace = "rainbowsea2" 定名空间的值。

同时编写Java程序的时候,使用上 namespace="rainbowsea2"的定名空间。


查询成功:
  1. @Test
  2.     public void testNamespace() {
  3.         SqlSession sqlSession = SqlSessionUtil.openSession();
  4.         // 执行SQL语句
  5.         // 正确的完整写法:namespace.id
  6.         List<Car> cars = sqlSession.selectList("rainbowsea2.selectAll");
  7.         // 遍历
  8.         cars.forEach(car -> {
  9.             System.out.println(car);
  10.         });
  11.         //sqlSession.commit();  查询不用提交,没有事务问题
  12.         sqlSession.close();
  13.     }
复制代码
实际上,本质上,mybatis中的 sqlId  的完备写法: namespace.id ,留意,之后都这么写了,这是完备正确的写法。
5. 总结:


  • 在sql语句中使用 #{map集合的key} 来完成传值,#{} 等同于JDBC中的 ? ,#{}就是占位符
  • 在mybatis当中不能使用 ? 占位符,必须使用 #{ } 来代替JDBC当中的  ?
    #{ }  和JDBC当中的 ? 是等效的。
  • { } 不可以空着,就算是只有一个传值,也不可以空着,随便写,都不可以空着。
  • pojo 对象的数据表 ORM 映射的 类对象,肯定要提供对应的 set 和 get 方法,不然 ,MyBatis 无法通过反射机制获取到相应所需要的信息的。 留意:占位符#{ }, 大括号内里写:pojo类的属性名
  • 如果采用POJO传参,#{} 里写的是get方法的方法名去掉get之后将剩下的单词首字母变小写(例如:getAge对应的是#{age},getUserName对应的是#{userName}),如果这样的get方法不存在会报错。
  • 留意:实在传参数的时候有一个属性 parameterType,这个属性用来指定传参的数据类型,不外这个属性是可以省略的
  • 添加/插入,执行 sqlSession.insert("Id", car); 方法
  • Java程序执行,删除操作,用sqlSession.delete("Id", 值) 方法,删除记录,只有一个占位符的时候,传一个值,MyBatis 可以自动载入,但是 #{} 不可以空着,要写上值
  • Java程序执行,修改/更新数据操作,用sqlSession.update("Id", 值) 方法,修改记录
  • 因为查询,没有修改的操作,是不需要事务操作的,所以我们不同提交数据,给数据库。
    这里我们查询的是一条记录,用 sqlSession.selectOne("id")  方法,返回一个 映射对象。

  • 你想让mybatis查询之后返回一个Java对象的话,至少你要告诉mybatis返回一个什么类型的Java对象,可以在标签中添加 resultType 属性,所赋值的对象是:全限定类名 ,用来指定查询要转换的类型:
  1. select 查询时,需要 pojo的类当中的映射的类对象中的属性名要与 对应数据表中的字段名一致,才能赋值成功,不然为 Null。可以使用  as 关键字,定义别名的方式,解决。后面有更好的解决方式。
复制代码

  • 我们查询的是多条记录,用 sqlSession.selectList("id")  方法,返回一个 List 集合,存储着我们的查询结果集。
  • 如果是返回的是键值对 的话,我们还可以用 sqlSession.selectMap("id") 方法 返回的是一个 Map 集合
  • 实际上,本质上,mybatis中的 sqlId  的完备写法: namespace.id ,留意,之后都这么写了,这是完备正确的写法。
  1. 在Java程序当中的写法:
  2.    // 执行SQL语句
  3.         List<Car> cars = sqlSession.selectList("rainbowsea2.selectAll");
  4. 实际上,本质上,mybatis中的sqlId的完整写法: namespace.id ,注意,之后都这么写了,这是完整正确的写法。
复制代码


  • 关于 MyBatis 的 CRUD 是重点内容,需要熟练掌握住。
6. 末了:

“在这个末了的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时候再次相遇。”


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

伤心客

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表