什么網(wǎng)站可以免費(fèi)做兼職網(wǎng)絡(luò)推廣的方式有哪些?
1. MyBatis 關(guān)于查詢語句上配置的詳細(xì)內(nèi)容
文章目錄
- 1. MyBatis 關(guān)于查詢語句上配置的詳細(xì)內(nèi)容
- 2. 準(zhǔn)備工作
- 3. SQL查詢結(jié)果,返回為POJO實(shí)體類型
- 4. SQL查詢結(jié)果,返回為L(zhǎng)ist<POJO\> 集合類型
- 5. SQL查詢結(jié)果,返回為Map 集合
- 6. SQL查詢結(jié)果,返回為L(zhǎng)ist<Map\>集合
- 7. SQL查詢結(jié)果,返回為Map<String,Map>
- 8. SQL查詢結(jié)果,返回總記錄條數(shù)
- 9. SQL查詢,resultMap 結(jié)果映射
- 9.1 第二種方式:使用 resultMap 進(jìn)行結(jié)果映射
- 9.2 第三種方式:開啟駝峰命名自動(dòng)映射
- 10. 總結(jié):
- 11. 最后:
2. 準(zhǔn)備工作
數(shù)據(jù)表結(jié)構(gòu)的設(shè)計(jì),數(shù)據(jù)表名為:t_car
t_car 表中的數(shù)據(jù)信息:
在pom.xml
文件當(dāng)中配置相關(guān)的依賴的 jar 包如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.rainbowsea</groupId><artifactId>mybatis-005-crud-blog</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><!-- mybatis 的依賴--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version></dependency><!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!-- 引入 logback的依賴,這個(gè)日志框架實(shí)現(xiàn)了slf4j 規(guī)范--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency></dependencies></project>
配置 logback 的配置文件,用于打印顯示,我們的日志信息,方便我們查看我們的運(yùn)行過程,效果。
<?xml version="1.0" encoding="UTF-8"?><configuration debug="false"><!-- 控制臺(tái)輸出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級(jí)別從左顯示5個(gè)字符寬度%msg:日志消息,%n是換行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!--mybatis log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/><!-- 日志輸出級(jí)別,logback日志級(jí)別包括五個(gè):TRACE < DEBUG < INFO < WARN < ERROR --><root level="DEBUG"><appender-ref ref="STDOUT"/><appender-ref ref="FILE"/></root></configuration>
配置 MyBatis 的核心配置文件,
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 使用 <package> 還可以將這個(gè)包下的所有的類的全部自動(dòng)起別名,別名就是簡(jiǎn)名,不區(qū)分大小寫 --><package name="com.rainbowsea.mybatis.pojo"/></typeAliases><environments default="mybatis"><environment id="mybatis"><!-- MANAGED 沒有用第三框架管理的話,都是會(huì)被提交的,沒有事務(wù)上的管理了 --><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="MySQL123"/></dataSource></environment></environments><mappers><!-- 這里也是可以使用 package 包名掃描,但是同樣的:對(duì)應(yīng)接口路徑要一致,接口名一致--><package name="com.rainbowsea.mybatis.mapper"></package></mappers>
</configuration>
對(duì)照 t_car 創(chuàng)建的ORM 映射的 Car 類
注意:在MyBatis 當(dāng)中對(duì)應(yīng)的ORM ,一般在框架里對(duì)應(yīng)的 Bean實(shí)體類,一定要實(shí)現(xiàn)該 set 和 get 方法以及無參數(shù)構(gòu)造方法,無法框架無法使用反射機(jī)制,進(jìn)行操作 。
建議用包裝類,這樣可以防止 Null的問題,因?yàn)?#xff08;簡(jiǎn)單類型 int num = null ,是不可以賦值為 null)的編譯無法通過
package com.rainbowsea.mybatis.pojo;public class Car {// 數(shù)據(jù)庫表當(dāng)中的字段應(yīng)該和pojo類的屬性一一對(duì)應(yīng)// 建議使用包裝類,這樣可以防止null的問題private Long id;private String carNum;private String brand;private Double guidePrice;private String produceTime;private String carType;public Car() {}public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {this.id = id;this.carNum = carNum;this.brand = brand;this.guidePrice = guidePrice;this.produceTime = produceTime;this.carType = carType;}@Overridepublic String toString() {return "Car{" +"id=" + id +", carNum='" + carNum + '\'' +", brand='" + brand + '\'' +", guidePrice=" + guidePrice +", produceTime='" + produceTime + '\'' +", catType='" + carType + '\'' +'}';}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getCarNum() {return carNum;}public void setCarNum(String carNum) {this.carNum = carNum;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public Double getGuidePrice() {return guidePrice;}public void setGuidePrice(Double guidePrice) {this.guidePrice = guidePrice;}public String getProduceTime() {return produceTime;}public void setProduceTime(String produceTime) {this.produceTime = produceTime;}public String getcarType() {return carType;}public void setcarType(String catType) {this.carType = catType;}
}
3. SQL查詢結(jié)果,返回為POJO實(shí)體類型
當(dāng)查詢的結(jié)果,有對(duì)應(yīng)的POJO 實(shí)體類,并且查詢結(jié)果只有一條時(shí):
實(shí)操:
對(duì)應(yīng)的接口
package com.rianbowsea.mybatis.mapper;import com.rianbowsea.mybatis.pojo.Car;public interface CarMapper {/*** 根據(jù) id 查詢 Car 的值* @param id* @return*/Car selectById(Long id);}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:對(duì)應(yīng)的接口的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!-- 使用 as 別名,讓POJO實(shí)體類當(dāng)中的屬性名與數(shù)據(jù)庫的查詢結(jié)果保持一致--><select id="selectById" resultType="Car">SELECT id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypeFROM `t_car`where id = #{id}</select></mapper>
運(yùn)行測(cè)試:
查詢id為 118 的記錄結(jié)果:
package com.rainbowsea.mybatis.test;import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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;public class CarMapperTest {@Testpublic void testSelectById() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Car car = mapper.selectById(118L);System.out.println(car);}
}
4. SQL查詢結(jié)果,返回為L(zhǎng)ist<POJO> 集合類型
當(dāng)查詢的記錄條數(shù)是多條的時(shí)候,必須使用集合接收。如果使用單個(gè)實(shí)體類接收會(huì)出現(xiàn)異常。
import com.rainbowsea.mybatis.pojo.Car;import java.util.List;public interface CarMapper {/*** 獲取所有的Car* @return*/List<Car> selectAll();}
注意:對(duì)于查詢結(jié)果返回多條記錄時(shí),resultType的值是(集合/數(shù)組存儲(chǔ)的元素的類型(除了Map集合是放Map集合本身))
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:對(duì)應(yīng)的接口的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!-- 使用 as 別名,讓POJO實(shí)體類當(dāng)中的屬性名與數(shù)據(jù)庫的查詢結(jié)果保持一致--><!-- 注意:對(duì)于查詢結(jié)果返回多條記錄時(shí),resultType的值是(集合/數(shù)組存儲(chǔ)的元素的類型(除了Map集合是放Map集合本身))--><select id="selectAll" resultType="Car">SELECT id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypeFROM t_car</select></mapper>
運(yùn)行測(cè)試:
查詢t_car 數(shù)據(jù)表中所有的記錄內(nèi)容:
package com.rainbowsea.mybatis.test;import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;public class CarMapperTest {@Testpublic void testSelectAll() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);List<Car> cars = mapper.selectAll();cars.forEach(car -> {System.out.println(car);});sqlSession.close();}}
如果返回多條記錄,采用單個(gè)實(shí)體類接收會(huì)怎樣 ?
查詢結(jié)果是一條的話可以使用List集合接收嗎?當(dāng)然可以。
就是List 集合當(dāng)中,只會(huì)存儲(chǔ)一個(gè)記錄的內(nèi)容POJO
5. SQL查詢結(jié)果,返回為Map 集合
當(dāng)返回的數(shù)據(jù),沒有合適的實(shí)體類POJO對(duì)應(yīng)的時(shí)候,可以采用Map集合進(jìn)行接受,字段名做 : key ,字段值做:value ,查詢結(jié)果可以保證只有一條數(shù)據(jù),則返回一個(gè)Map集合。
注意:只有返回的是單個(gè)記錄的時(shí)候,才可以用單個(gè)Map集合存儲(chǔ)接受
Mybatis 在 查詢結(jié)果放到 Map 集合中存放的方式是:
* Map<String, Object>* key value* "id" 131* "car_num" 999* "brand" 小米su7* 查詢數(shù)據(jù)庫中的字段名 對(duì)于單個(gè)對(duì)應(yīng)字段的值
?
import com.rainbowsea.mybatis.pojo.Car;import java.util.List;
import java.util.Map;public interface CarMapper {/*** Mybatis 在 查詢結(jié)果放到 Map 集合中存放的方式是:* Map<String, Object>* k v* "id" 131* "car_num" 999* "brand" 小米su7* 查詢 對(duì)于單個(gè)對(duì)應(yīng)字段的值* 數(shù)據(jù)庫中* 的字段名*** @param id* @return*/Map<String,Object> selectByIdRetMap(Long id);
}
注意:對(duì)于查詢結(jié)果返回多條記錄時(shí),resultType的值是(集合/數(shù)組存儲(chǔ)的元素的類型(除了Map集合是放Map集合本身))resultMap=“map”,這是因?yàn)閙ybatis內(nèi)置了很多別名。【參見mybatis開發(fā)手冊(cè)】 https://mybatis.net.cn/
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:對(duì)應(yīng)的接口的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!-- 使用 as 別名,讓POJO實(shí)體類當(dāng)中的屬性名與數(shù)據(jù)庫的查詢結(jié)果保持一致--><!-- 注意:對(duì)于查詢結(jié)果返回多條記錄時(shí),resultType的值是(集合/數(shù)組存儲(chǔ)的元素的類型(除了Map集合是放Map集合本身))--><select id="selectByIdRetMap" resultType="Map">SELECT id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypeFROM t_carwhere id = #{id}</select>
</mapper>
運(yùn)行測(cè)試:
查詢 id 為 118 的記錄
package com.rainbowsea.mybatis.test;import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;public class CarMapperTest {@Testpublic void testSelectByIdRetMap() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Map<String, Object> cars = mapper.selectByIdRetMap(118L);System.out.println(cars);sqlSession.close();}}
注意:只有返回的是單個(gè)記錄的時(shí)候,才可以用單個(gè)Map集合存儲(chǔ)接受 ,如果是多個(gè)記錄的話,
可以將Map集合放到List集合中。
反過來,如果返回的不是一條記錄,是多條記錄的話,只采用單個(gè)Map集合接收,這樣同樣會(huì)出現(xiàn)之前的異常:TooManyResultsException
6. SQL查詢結(jié)果,返回為L(zhǎng)ist<Map>集合
查詢結(jié)果條數(shù)大于等于 1 條數(shù)據(jù)時(shí),則可以返回一個(gè)存儲(chǔ) Map 集合的 List 集合。List<Map> 等同于 List<Car>
注意: 這個(gè) resultType 不是 List 是 map ,注意:除了單個(gè)特殊的 Map 集合的話(因?yàn)镸ap當(dāng)中存在多個(gè)元素類型,無法斷定用其中的那個(gè)存儲(chǔ)的),其他的都是數(shù)組/集合當(dāng)中存放的數(shù)據(jù)的元素類型
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:對(duì)應(yīng)的接口的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!-- 使用 as 別名,讓POJO實(shí)體類當(dāng)中的屬性名與數(shù)據(jù)庫的查詢結(jié)果保持一致--><!-- 這個(gè) resultType 不是List 是 map ,注意:除了單個(gè)特殊的 Map --><!-- 這個(gè) resultType 不是List 是 map ,注意:除了單個(gè)特殊的 Map 集合的話(因?yàn)镸ap當(dāng)中存在多個(gè)元素類型,無法斷定用其中的那個(gè)存儲(chǔ)的),其他的都是數(shù)組/集合當(dāng)中存放的數(shù)據(jù)的元素類型--><select id="selectAllRetListMap" resultType="map">SELECT id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypeFROM `t_car` </select></mapper>
測(cè)試運(yùn)行程序:
package com.rainbowsea.mybatis.test;import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;public class CarMapperTest {@Testpublic void testSelectAllRetListMap() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);List<Map<String, Object>> cars = mapper.selectAllRetListMap();cars.forEach(car->{System.out.println(car);});sqlSession.close();}}
7. SQL查詢結(jié)果,返回為Map<String,Map>
這里我們拿Car的id做 最外面的Map 的key,以后取出對(duì)應(yīng)的Map集合時(shí)更方便。最外面里面包含一個(gè)小Map集合
這里我們需要使用 @MapKey
注解,該注解的作用就是將:將查詢結(jié)果的 id 字段的值作為整個(gè)Map(最外面的那個(gè)Map)集合的key。
這里你想將查詢結(jié)果中的那個(gè)字段的值,賦值給“最外面的Map”集合的 key ,就填寫對(duì)應(yīng)上的查詢上的字段名即可
package com.rainbowsea.mybatis.mapper;import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.MapKey;import java.util.List;
import java.util.Map;public interface CarMapper {/*** 查詢所有的Car,返回一個(gè)Map集合* Map集合的key是每條記錄的主鍵值* Map集合的value是每條記錄* @return*/@MapKey("id") // 將查詢結(jié)果的id字段的值作為整個(gè)Map集合的key。Map<Long,Map<String,Object>> selectAllRetMap();}
注意:我們這里是一個(gè)Map中套裝一個(gè)Map,
Map集合比較特殊(存在兩個(gè)值:key,value) 所以要
繼續(xù)使用Map存儲(chǔ)查詢結(jié)果
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:對(duì)應(yīng)的接口的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!-- 使用 as 別名,讓POJO實(shí)體類當(dāng)中的屬性名與數(shù)據(jù)庫的查詢結(jié)果保持一致-->
<!-- 注意:這里是用 Map集合進(jìn)行接受的--><select id="selectAllRetMap" resultType="Map">SELECT id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypeFROM `t_car`</select></mapper>
運(yùn)行測(cè)試:
查詢t_car 數(shù)據(jù)表中的所有內(nèi)容。
package com.rainbowsea.mybatis.test;import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;public class CarMapperTest {@Testpublic void testSelectAllRetMap() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Map<Long,Map<String,Object>> cars = mapper.selectAllRetMap();System.out.println(cars);sqlSession.close();}}
8. SQL查詢結(jié)果,返回總記錄條數(shù)
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.MapKey;import java.util.List;
import java.util.Map;public interface CarMapper {/*** 獲取Car的總記錄條數(shù)* @return*/Long selectTotal();
}
需要注意的是: select count(具體某個(gè)字段的話,是不會(huì)記錄null值的個(gè)數(shù)的),所以我們可以用 select count(1) from t_car ,恒為真的方式,查詢(這樣就包括了為 null 的值的個(gè)數(shù)了)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:對(duì)應(yīng)的接口的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!-- <select id="selectTotal" resultType="java.lang.Long"> ,也可以用別名--><select id="selectTotal" resultType="Long">select count(1)from t_car</select></mapper>
運(yùn)行測(cè)試:
查詢 t_car 數(shù)據(jù)表中的所有記錄條數(shù)。
import java.io.IOException;
import java.util.List;
import java.util.Map;public class CarMapperTest {@Testpublic void testSelectTotal() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Long count = mapper.selectTotal();System.out.println("總記錄條數(shù)" + count);sqlSession.close();}
}
9. SQL查詢,resultMap 結(jié)果映射
我們知道,要將 select 查詢的結(jié)果集存儲(chǔ)到對(duì)應(yīng)的POJO實(shí)體類當(dāng)中的必須要將查詢的字段名和POJO實(shí)體類的屬性名兩者保持一致 ,但是我們的數(shù)據(jù)庫的命名規(guī)范是下劃線 ,而在Java當(dāng)中的命名規(guī)范是駝峰命名 方式,兩者是不一致的。而想要將這兩者在不修改自身的屬性名字也能達(dá)到一個(gè)兩者名字保持一致的方案有 ,如下三種方式:
- 第一種方式:使用
AS
關(guān)鍵字給列起別名 - 第二種方式:使用 resultMap 進(jìn)行結(jié)果映射
- 第三種方式:開啟MyBatis 的駝峰命名自動(dòng)映射(配置 settings )
第一方式:我們上述的操作都是,使用的這種方式,下面就不多贅述了。
我們來學(xué)習(xí)一下,第二,三種方式。
9.1 第二種方式:使用 resultMap 進(jìn)行結(jié)果映射
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.MapKey;import java.util.List;
import java.util.Map;public interface CarMapper {/*** 查詢所有的Car信息,使用resultMap標(biāo)簽進(jìn)行結(jié)果映射* @return*/List<Car> selectAllByResultMap();
}
resultMap 1.專門定義一個(gè)結(jié)果映射,在這個(gè)結(jié)果映射當(dāng)中指定數(shù)據(jù)庫表的字段名和Java類的屬性名的對(duì)應(yīng)關(guān)系
type屬性,用來指定POJO類的類名
id屬性,指定resultMap的唯一標(biāo)識(shí),這個(gè)id將來要在select標(biāo)簽中使用,啟用了別名機(jī)制, 也可以用別名注意:resultMap屬性的值必須和resultMap標(biāo)簽中id屬性值一致
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:對(duì)應(yīng)的接口的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!-- resultMap 1.專門定義一個(gè)結(jié)果映射,在這個(gè)結(jié)果映射當(dāng)中指定數(shù)據(jù)庫表的字段名和Java類的屬性名的對(duì)應(yīng)關(guān)系2.type屬性,用來指定POJO類的類名3.id屬性,指定resultMap的唯一標(biāo)識(shí),這個(gè)id將來要在select標(biāo)簽中使用--><!-- <resultMap id="carResultMap" type="com.rainbowsea.mybatis.pojo.Car">--><!-- 啟用了別名機(jī)制, 也可以用別名--><resultMap id="carResultMap" type="Car"><!-- 如果數(shù)據(jù)表中有主鍵,一般都是有主鍵的,要不然不符合數(shù)據(jù)庫設(shè)計(jì)第一范式--><!-- 如果有主鍵,建議這里配置一個(gè)id的標(biāo)簽,注意:這不是必須的,但是官方的解釋是:這樣的配置可以讓mybatis 提高效率--><id property="id" column="id"></id><!-- property 后面填寫的值是:POJO類的屬性名--><!-- column 后面填寫數(shù)據(jù)庫表查詢顯示的的字段名(用了別名的話,是別名)--><result property="carNum" column="car_num"></result><!--當(dāng)屬性名和數(shù)據(jù)庫列名一致時(shí),可以省略。但建議都寫上。--><!--javaType用來指定屬性類型。jdbcType用來指定列類型。一般可以省略。--><result property="brand" column="brand" javaType="string" jdbcType="VARCHAR"/><result property="guidePrice" column="guide_price"></result><result property="produceTime" column="produce_time"></result><result property="carType" column="car_type"></result></resultMap><!-- select標(biāo)簽的resultMap的屬性,用來指定使用哪個(gè)結(jié)果映射,resultMap后面的值是resultMap的id--><!--resultMap屬性的值必須和resultMap標(biāo)簽中id屬性值一致。--><select id="selectAllByResultMap" resultMap="carResultMap">SELECT id,car_num,brand,guide_price,produce_time,car_typeFROM `t_car`</select></mapper>
運(yùn)行測(cè)試:
查詢 t_car 數(shù)據(jù)表中的所有內(nèi)容。
import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;public class CarMapperTest {@Testpublic void testSelectAllByResultMap() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);List<Car> cars = mapper.selectAllByResultMap();cars.forEach(car -> {System.out.println(car);});sqlSession.close();}
}
9.2 第三種方式:開啟駝峰命名自動(dòng)映射
使用這種方式的前提是:屬性名遵循Java駝峰 命名規(guī)范,數(shù)據(jù)庫表列名遵循SQL的下劃線 命名規(guī)范。
- Java命名規(guī)范:首字母小寫,后面每個(gè)單詞首字母大寫,遵循駝峰命名方式
- SQL命名規(guī)范:全部小寫,單詞之間采用下劃線分割
比如以下的對(duì)應(yīng)關(guān)系:
比如以下的對(duì)應(yīng)關(guān)系:
POJO 實(shí)體類中的屬性名 | 數(shù)據(jù)庫表的列名 |
---|---|
carNum | car_num |
carType | car_type |
produceTime | produce_time |
如何啟用該功能,在 mybatis-config.xml
文件中進(jìn)行配置:
注意:setting 標(biāo)簽方式的位置,可以根據(jù)錯(cuò)誤提示進(jìn)行修正位置。
<!-- mybatis 的全局設(shè)置--><settings>
<!-- 是否開啟駝峰命名自動(dòng)映射,即從經(jīng)典數(shù)據(jù)庫列名 A_COLUMN 映射到經(jīng)典 Java 屬性名 aColumn。 默認(rèn)是 false 不開啟,true 表示開啟--><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- mybatis 的全局設(shè)置--><settings>
<!-- 是否開啟駝峰命名自動(dòng)映射,即從經(jīng)典數(shù)據(jù)庫列名 A_COLUMN 映射到經(jīng)典 Java 屬性名 aColumn。 默認(rèn)是 false 不開啟,true 表示開啟--><setting name="mapUnderscoreToCamelCase" value="true"/></settings><!-- 起別名--><typeAliases><!-- 使用 <package> 還可以將這個(gè)包下的所有的類的全部自動(dòng)起別名,別名就是簡(jiǎn)名,不區(qū)分大小寫 --><package name="com.rainbowsea.mybatis.pojo"/></typeAliases><environments default="mybatis"><environment id="mybatis"><!-- MANAGED 沒有用第三框架管理的話,都是會(huì)被提交的,沒有事務(wù)上的管理了 --><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="MySQL123"/></dataSource></environment></environments><mappers><!-- 這里也是可以使用 package 包名掃描,但是同樣的:對(duì)應(yīng)接口路徑要一致,接口名一致--><package name="com.rainbowsea.mybatis.mapper"></package></mappers>
</configuration>
開啟后運(yùn)行測(cè)試:
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.MapKey;import java.util.List;
import java.util.Map;public interface CarMapper {/*** mybatis 全局設(shè)置,駝峰命名映射* @return*/List<Car> selectAllByMapUnderscoreToCamelCase();}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:對(duì)應(yīng)的接口的全限定類名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper">
<!-- 啟用了 mybatis 全局設(shè)置,駝峰命名映射 --><select id="selectAllByMapUnderscoreToCamelCase" resultType="Car">SELECT id,car_num,brand,guide_price,produce_time,car_typeFROM `t_car`</select></mapper>
運(yùn)行測(cè)試:
查詢 t_car 數(shù)據(jù)表的所有記錄
import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
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.util.List;
import java.util.Map;public class CarMapperTest {@Testpublic void testSelectAllByMapUnderscoreToCamelCase() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);List<Car> cars = mapper.selectAllByMapUnderscoreToCamelCase();cars.forEach(car -> {System.out.println(car);});sqlSession.close();}
}
10. 總結(jié):
注意:對(duì)于查詢結(jié)果返回多條記錄時(shí),resultType的值是(集合/數(shù)組存儲(chǔ)的元素的類型(除了Map集合是放Map集合本身))
注意:只有返回的是單個(gè)記錄的時(shí)候,才可以用單個(gè)Map集合存儲(chǔ)接受 ,如果是多個(gè)記錄的話,可以將Map集合放到List集合中。反過來,如果返回的不是一條記錄,是多條記錄的話,只采用單個(gè)Map集合接收,這樣同樣會(huì)出現(xiàn)之前的異常:TooManyResultsException
這里我們需要使用
@MapKey
注解,該注解的作用就是將:將查詢結(jié)果的 id 字段的值作為整個(gè)Map(最外面的那個(gè)Map)集合的key。這里你想將查詢結(jié)果中的那個(gè)字段的值,賦值給“最外面的Map”集合的 key ,就填寫對(duì)應(yīng)上的查詢上的字段名即可
resultMap 結(jié)果映射: 注意:resultMap屬性的值必須和resultMap標(biāo)簽中id屬性值一致。property 后面填寫的值是:POJO類的屬性名;column 后面填寫數(shù)據(jù)庫表查詢顯示的的字段名(用了別名的話,是別名)
開啟駝峰命名自動(dòng)映射。屬性名遵循Java駝峰 命名規(guī)范,數(shù)據(jù)庫表列名遵循SQL的下劃線 命名規(guī)范。,同時(shí)注意:注意:setting 標(biāo)簽方式的位置,可以根據(jù)錯(cuò)誤提示進(jìn)行修正位置。
如果查詢的結(jié)果是一個(gè)數(shù)值,則可以用數(shù)值類型進(jìn)行接受。
11. 最后:
“在這個(gè)最后的篇章中,我要表達(dá)我對(duì)每一位讀者的感激之情。你們的關(guān)注和回復(fù)是我創(chuàng)作的動(dòng)力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會(huì)將你們的鼓勵(lì)留在心底,繼續(xù)在其他的領(lǐng)域奮斗。感謝你們,我們總會(huì)在某個(gè)時(shí)刻再次相遇?!?/p>