前置工作准备
- 创建Maven项目 , 引入依赖(mybatis依赖 ,mysql 驱动依赖 ,junit依赖 ,logback 依赖)
- 将xml文件放到类的根路径下
- 提供com.north.mybatis.utils.SqlSessionUtil工具类
- 创建测试用例:com.north.mybatis.CarMapperTest
补充知识:什么是CRUD
C: Create增
R: Retrieve查(检索)
U: Update改
D: Delete删
1. insert(Create )
先说理论知识 : 在sql语句中使用 #{map集合的key}来完成传值 等同于JDBC中的 ? ,#{}就是占位符
<insert id="insertCar">insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)values(null,'1003','丰田霸道',30.0,'2000-10-11','燃油车');</insert>
上述代码的问题是:
- 值 显然是写死到配置文件中的。
- 这个在实际开发中是不存在的。一定是前端的form表单提交过来数据。然后将值传给sql语句。
例如:JDBC的代码是怎么写的?String sql = "insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)";
在JDBC当中占位符采用的是?,在mybatis当中是什么呢?
和?等效的写法是:#{}
在mybatis当中不能使用?占位符,必须使用 #{} 来代替JDBC当中的 ?
{} 和 JDBC当中的 ? 是等效的。
insert的细节之处
java程序中使用POJO类给SQL语句的占位符传值:
- 注意:占位符#{},大括号里面写:pojo类的属性名 , 但是这样说也并不是很严谨
严格意义上来说:如果使用POJO对象传递值的话,#{}这个大括号中到底写什么?
- 写的是get方法的方法名去掉get,然后将剩下的单词首字母小写,然后放进去。
- 例如:getUsername() --> #
也就是说mybatis在底层给 ? 传值的时候,先要获取值,怎么获取的 ?
- 调用了pojo对象的get方法。例如:car.getCarNum(),car.getCarType(),car.getBrand()
如果采用map集合传参,#{} 里写的是map集合的key,如果key不存在不会报错,数据库表中会插入NULL。
代码演示 ,这里我自己吸取之前的教训 ,把基本完整的给写出来 ,防止以后再来看的话 , 不知道都代表着是什么意思😊😊😊
工具类代码:
public class SqlSessionUtil {// 工具类的构造方法一般都是私有化的。// 工具类中所有的方法都是静态的,直接采用类名即可调用。不需要new对象。// 为了防止new对象,构造方法私有化。private SqlSessionUtil(){}private static SqlSessionFactory sqlSessionFactory;// 类加载时执行// SqlSessionUtil工具类在进行第一次加载的时候,解析mybatis-config.xml文件。创建SqlSessionFactory对象。static {try {sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));} catch (IOException e) {throw new RuntimeException(e);}}/*public static SqlSession openSession(){SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();// SqlSessionFactory对象:一个SqlSessionFactory对应一个environment,一个environment通常是一个数据库。SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));SqlSession sqlSession = sqlSessionFactory.openSession();return sqlSession;}*//*** 获取会话对象。* @return 会话对象*/public static SqlSession openSession(){return sqlSessionFactory.openSession();}
}
测试类:
@Testpublic void testInsertCarByPOJO() {SqlSession sqlSession = SqlSessionUtil.openSession();// 封装数据Car car = new Car(null , "1005" , "比亚迪汉" , 30.0 , "2020-11-11" , "新能源");int rows = sqlSession.insert("insertCar" , car);System.out.println("插入成功的行数:" + rows);sqlSession.commit();sqlSession.close();}
CarMapper.xml文件中的insert标签:
<insert id="insertCar">insert into t_car(id , car_num , brand , guide_price , produce_time , car_type)values (null , #{carNum} , #{brand} , #{guidePrice} , #{produceTime} , #{carType})</insert>
2. delete (Delete)
注意:如果占位符只有一个,那么#{}的大括号里可以随意。但是最好见名知意。
需求:根据id进行删除数据
CarMapper.xml文件中的delete标签:
<delete id="deleteCar">delete from t_car where id = #{id}</delete>
测试类:
@Testpublic void testDeleteById() {SqlSession sqlSession = SqlSessionUtil.openSession();int rows = sqlSession.delete("deleteCar", 16);System.out.println("删除的行数:" + rows);sqlSession.commit();sqlSession.close();}
3. update(Update)
根据id修改某条数据的代码演示
CarMapper.xml文件中的update标签:
<update id="updateCar">update t_carsetcar_num = #{carNum} ,brand = #{brand} ,guide_price = #{guidePrice} ,produce_time = #{produceTime} ,car_type = #{carType}whereid = #{id}</update>
测试类:
@Testpublic void testUpdateById() {SqlSession sqlSession = SqlSessionUtil.openSession();Car car = new Car(4L , "3333" , "梅特赛斯" , 146.8 , "2018-11-11" , "燃油车");int rows = sqlSession.update("updateCar", car);System.out.println("受影响的行数:" + rows);sqlSession.commit();sqlSession.close();}
4. select(Retrieve)
select语句和其它语句不同的是:查询会有一个结果集
4.1 查询一条数据
其中 ,查一个,根据主键查询的话,返回的结果一定是一个。
需求:根据id进行查询
需要特别注意的是:
select标签中resultType属性,这个属性用来告诉mybatis,查询结果集封装成什么类型的java对象。你需要告诉mybatis。
resultType通常写的是:全限定类名。
注意:select语句查询的时候,查询结果集的列名是可以使用as关键字起别名的。
查询的时候需要在select标签中进行封装结果接映射 ,也就是写上resultType属性 , 不然会进行报错
CarMapper.xml文件中的select标签:
<select id="selectById" resultType="com.north.mybatis.pojo.Car">selectid ,car_num as carNum ,brand ,guide_price as guidePrice ,produce_time as produceTime ,car_type as carTypefromt_carwhereid = #{id}</select>
测试类:
@Testpublic void testSelectById() {SqlSession sqlSession = SqlSessionUtil.openSession();Object selectOne = sqlSession.selectOne("selectById", 1);System.out.println(selectOne);sqlSession.close();}
查询结果展示:
4.2 查询多条数据
需求:查询所有数据
需要注意的是:
resultType还是指定要封装的结果集的类型。不是指定List类型,是指定List集合中元素的类型。
selectList方法:mybatis通过这个方法就可以得知你需要一个List集合。它会自动给你返回一个List集合。
CarMapper.xml文件中的select标签:
<select id="selectAll" resultType="com.north.mybatis.pojo.Car">selectid ,car_num as carNum ,brand ,guide_price as guidePrice ,produce_time as produceTime ,car_type as carTypefromt_car</select>
测试类:
@Testpublic void testSelectAll() {SqlSession sqlSession = SqlSessionUtil.openSession();List<Object> selectAll = sqlSession.selectList("selectAll");selectAll.forEach(car -> System.out.println(car));sqlSession.close();}
运行结果展示:
5. 关于SQL Mapper的namespace
namespace的作用
在sql mapper.xml文件当中有一个namespace,这个属性是用来指定命名空间的。用来防止id重复。
实际上,本质上,mybatis中的sqlId的完整写法:namespace.id