模块名:mybatis-007-select
打包方式:jar
引入依赖:mysql驱动依赖、mybatis依赖、logback依赖、junit依赖。
引入配置文件:jdbc.properties、mybatis-config.xml、logback.xml
创建pojo类:Car
创建Mapper接口:CarMapper
创建Mapper接口对应的映射文件:com/powernode/mybatis/mapper/CarMapper.xml
创建单元测试:CarMapperTest
拷贝工具类:SqlSessionUtil
4.0.0
com.powernode
mybatis-008-select
1.0-SNAPSHOT
jar
org.mybatis
mybatis
3.5.10
mysql
mysql-connector-java
8.0.30
ch.qos.logback
logback-classic
1.2.11
junit
junit
4.13.2
test
17
17
UTF-8
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Car;
/**
* @author wuw
* @since 2023-04-11 10:13:56
*/
public interface CarMapper {
}
package com.powernode.mybatis.pojo;
/**
* @author wuw
* @since 2023-02-01 15:16:01
*/
public class Car {
//数据库表中的字段应该和pojo类的属性一一对应
private Long id;
private String carNum;
private String brand;
private Double guidePrice;
private String produceTime;
private String carType;
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;
}
public Car(){
}
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 carType) {
this.carType = carType;
}
@Override
public String toString() {
return "car{" +
"id=" + id +
", carNum='" + carNum + '\'' +
", brand='" + brand + '\'' +
", guidePrice=" + guidePrice +
", produceTime='" + produceTime + '\'' +
", carType='" + carType + '\'' +
'}';
}
}
package com.powernode.mybatis.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;
/**
* @author wuw
* @since 2023-04-04 09:42:28
*/
public class SqlSessionUtil {
private static SqlSessionFactory sqlSessionFactory;
/**
* 类加载时初始化sqlSessionFactory对象
*/
static {
try {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (Exception e) {
e.printStackTrace();
}
}
private static ThreadLocal local = new ThreadLocal<>();
/**
* 每调用一次openSession()可获取一个新的会话,该会话支持自动提交。
*
* @return 新的会话对象
*/
public static SqlSession openSession() {
SqlSession sqlSession = local.get();
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession();
local.set(sqlSession);
}
return sqlSession;
}
/**
* 关闭SqlSession对象
* @param sqlSession
*/
public static void close(SqlSession sqlSession){
if (sqlSession != null) {
sqlSession.close();
}
local.remove();
}
}
当查询的结果,有对应的实体类,并且查询结果只有一条时:
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Car;
/**
* @author wuw
* @since 2023-04-11 10:13:56
*/
public interface CarMapper {
/**
* 根据Id查Car信息
* @param Id
* @return
*/
Car selectById(Long Id);
}
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.pojo.Car;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.junit.Test;
public class CarMapperTest {
@Test
public void testSelectById(){
CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
Car car = mapper.selectById(10L);
System.out.println(car);
}
}
查询结果是一条的话可以使用List集合接收吗?当然可以。
/**
* 根据id主键查询:结果最多只有一条,可以放到List集合中吗?
* @return
*/
List selectByIdToList(Long id);
@Test
public void testSelectByIdToList(){
CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
List cars = mapper.selectByIdToList(9L);
System.out.println(cars);
}
当查询的记录条数是多条的时候,必须使用集合接收。如果使用单个实体类接收会出现异常。
/**
* 查询所有的Car
* @return
*/
List selectAll();
@Test
public void testSelectAll(){
CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
List cars = mapper.selectAll();
cars.forEach(car -> System.out.println(car));
}
如果返回多条记录,采用单个实体类接收会怎样?
/**
* 查询多条记录,采用单个实体类接收会怎样?
* @return
*/
Car selectAll2();
@Test
public void testSelectAll2(){
CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
Car car = mapper.selectAll2();
System.out.println(car);
}
当返回的数据,没有合适的实体类对应的话,可以采用Map集合接收。字段名做key,字段值做value。
查询如果可以保证只有一条数据,则返回一个Map集合即可。
/**
* 通过id查询一条记录,返回Map集合
* @param id
* @return
*/
Map selectByIdRetMap(Long id);
resultMap="map",这是因为mybatis内置了很多别名。【参见mybatis开发手册】
@Test
public void testSelectByIdRetMap(){
CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
Map car = mapper.selectByIdRetMap(31L);
System.out.println(car);
}
当然,如果返回一个Map集合,可以将Map集合放到List集合中吗?当然可以,这里就不再测试了。
反过来,如果返回的不是一条记录,是多条记录的话,只采用单个Map集合接收,这样同样会出现之前的异常:TooManyResultsException
查询结果条数大于等于1条数据,则可以返回一个存储Map集合的List集合。List
/**
* 查询所有的Car,返回一个List集合。List集合中存储的是Map集合。
* @return
*/
List
@Test
public void testSelectAllRetListMap(){
CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
List
拿Car的id做key,以后取出对应的Map集合时更方便
/**
* 获取所有的Car,返回一个Map集合。
* Map集合的key是Car的id。
* Map集合的value是对应Car。
* @return
*/
@MapKey("id")
Map> selectAllRetMap();
@Test
public void testSelectAllRetMap(){
CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
Map> cars = mapper.selectAllRetMap();
System.out.println(cars);
}
查询结果的列名和java对象的属性名对应不上怎么办?
- 第一种方式:as 给列起别名
- 第二种方式:使用resultMap进行结果映射
- 第三种方式:是否开启驼峰命名自动映射(配置settings)
之前用的第一种方式,现在介绍一下第二和第三种方式
/**
* 查询所有Car,使用resultMap进行结果映射
* @return
*/
List selectAllByResultMap();
@Test
public void testSelectAllByResultMap(){
CarMapper carMapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
List cars = carMapper.selectAllByResultMap();
System.out.println(cars);
}
执行结果正常。
使用这种方式的前提是:属性名遵循Java的命名规范,数据库表的列名遵循SQL的命名规范。
Java命名规范:首字母小写,后面每个单词首字母大写,遵循驼峰命名方式。
SQL命名规范:全部小写,单词之间采用下划线分割。
比如以下的对应关系:
实体类中的属性名 |
数据库表的列名 |
carNum |
car_num |
carType |
car_type |
produceTime |
produce_time |
如何启用该功能,在mybatis-config.xml文件中进行配置:
/**
* 查询所有Car,启用驼峰命名自动映射
* @return
*/
List selectAllByMapUnderscoreToCamelCase();
@Test
public void testSelectAllByMapUnderscoreToCamelCase(){
CarMapper carMapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
List cars = carMapper.selectAllByMapUnderscoreToCamelCase();
System.out.println(cars);
}
执行结果正常。
需求:查询总记录条数
/**
* 获取总记录条数
* @return
*/
Long selectTotal();
@Test
public void testSelectTotal(){
CarMapper carMapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
Long total = carMapper.selectTotal();
System.out.println(total);
}