Review-MyBatis

2023-11-18

MyBatis

1 学习方法

MyBatis框架功能与Hibernate一样。
都是持久化框架。都是操作JDBC。做ORM框架。
1 MyBatis框架比Hibernate小。
2 做的是针对SQL语句查询结果进行封装。

2 MyBatis框架是什么?

MyBatis是一个针对SQL语句的ORM持久化框架。
1 针对SQL语句
	在MyBatis框架中,我们要写SQL语句,针对SQL查询的结果进行封装。
2 ORM
	将查询结果可以封装成一个实体对象。
3 持久化
	使用JDBC进行数据库操作。

3 编写第一个MyBatis框架的工程

3.1 创建工程并导入MyBatis的jar

3.2 配置MyBatis框架

在src目录下创建mybatis.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.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://127.0.0.1:3306/t2?useUnicode=true&amp;characterEncoding=utf8" />
				<property name="username" value="root" />
				<property name="password" value="root" />
			</dataSource>
		</environment>
	</environments>
</configuration>

3.3 ORM映射

1 数据库表:goods_type

2 编写实体类:GoodsType
public class GoodsType {
private int typeId;
private String typeName;

3.4 编写SQL语句(写在XML文件)

在MyBatis框架中SQL语句是程序员自己编写。
在MyBatis框架时,编写的SQL语句是独立于java源文件之外。
1 编写在xml配置文件(推荐)
2 编写在方法的注解

注意:编写一个与类名同名的xml文件。
在这个xml中编写对应的CURD的SQL语句。

<?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">
<mapper namespace="com.zpark.tea_mgr.domain.GoodsType">
	<select id="findAll" resultType="com.zpark.tea_mgr.domain.GoodsType">
		select * from goods_type
	</select>
</mapper>

resultType="com.no1.domain.GoodsType" 表示查询结果的每一条记录封装成指定的类型。
(只有在字段名称与属性名称一致时可用)

3.5 在MyBatis配置文件中注册SQL的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">……</environments>
	<mappers>
		<mapper resource="com/zpark/tea_mgr/domain/GoodsType.xml" />
	</mappers>
</configuration>

3.6 获得一个SqlSession的实例

在MyBatis中使用核心组件SqlSession进行CRUD操作。
	@Before
	public void before() {
		try {
			String resource = "mybatis.xml";
			Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
			this.sqlSession = ssf.openSession();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

3.7 通过SqlSession组件的方法调用CRUD

查询所有

	public void test01() {
		try {
List<GoodsType> goodsTypeList = this.sqlSession.selectList("com.zpark.tea_mgr.domain.GoodsType.findAll");
			for (GoodsType goodsType : goodsTypeList) {
				System.out.println(goodsType);
			}
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			this.sqlSession.close();
		}
	}

4 配置本地DTD文件

Q:为什么要配置DTD文件?

DTD相当于是编写XML文件的代码提示蓝本,在XML文件中声明DTD的ID或者URL,再在MyEclipse或者Eclipse中配置一下,重新打开这个XML文件,就可以用alt+/获得像编写JAVA代码一样的提示功能。具体的配置方法可以百度一下~
当然,这个文件主要的功能是验证XML文件编写的合法性,也就是一个约束,要求你只能按DTD定义的格式写。
建议去看一下XML相关知识。

4.1 找到本地dtd文件

在这里插入图片描述

4.2 在工具中绑定

在这里插入图片描述

5 当表中字段名称与实体类中属性名称不一致

5.1 创建数据库表 goods

在这里插入图片描述

5.2 创建实体类

在这里插入图片描述

5.3 编写Goods.xml文件

5.4 在mybatis.xml文件中注册Goods.xml文件
在这里插入图片描述

5.5 完成CRUD并测试

6 使用Mapper接口开发MyBatis项目

在实际开发中,不直接使用SqlSession的实例,而是使用Mapper接口,构建dao层。

6.1 Mapper接口是什么

映射器是你创建的绑定映射语句的接口(interface)
映射器接口的实例可以从SqlSession中获得

6.2 创建工程并导入jar

6.3 编写实体类

public class Goods {
//	goods_id	int
	private int goodsId;
//	goods_name	varchar
	private String goodsName;
//	goods_price	double
	private double goodsPrice;
//	goods_num	int
	private int goodsNum;
//	goods_type	int
	private int goodsType;
	}

6.4 编写Mapper接口

Mapper接口相当于Hebernate中的DAO
在这个接口中声明针对Goods这个实体类进行哪些CRUD操作

public interface GoodsMapper {
	public List<Goods> findAll();
}

6.5 编写GoodsMapper接口的实现类

在MyBatis框架中,接口的实现类是一个XML文件
在GoodsMapper接口的同目录创建一个叫GoodsMapper.xml文件

<mapper namespace="com.zpark.tea_mgr.mapper.GoodsMapper">
	<select id="findAll" resultMap="resultGoods">
		select * from goods
	</select>
	<resultMap type="com.zpark.tea_mgr.domain.Goods" id="resultGoods">
		<id property="goodsId" column="goods_id" javaType="int" />
		<result property="goodsName" column="goods_name" javaType="java.lang.String" />
		<result property="goodsPrice" column="goods_price" javaType="double" />
		<result property="goodsNum" column="goods_num" javaType="int" />
		<result property="goodsType" column="goods_type" javaType="int" />
	</resultMap>
</mapper>

6.6 在mybatis.xml文件中注册GoodsMapper.xml文件

<configuration>
	<environments default="development">……</environments>
	<mappers>
		<mapper resource="com/zpark/tea_mgr/mapper/GoodsMapper.xml" />
	</mappers>
</configuration>

6.7 从SqlSession中获得Mapper接口的实例

GoodsMapper goodsMapper = this.sqlSession.getMapper(GoodsMapper.class);

7 带参数的查询

7.1 只有一个参数时

只有一个参数时,在xml文件中只要制定类型就可以
在sql语句中可以使用任意名称的参数

public Goods findById(int id);
<select id="findById"  parameterType="int"  resultMap="resultGoods">
	select * from goods 
	where goods_id = #{id}
</select>

7.2 多个参数时

按价格区间查询的方法

public List<Goods> findByPrice(
@Param("minPrice") double minPrice, @Param("maxPrice") double maxPrice);
<select id="findByPrice" resultMap="resultGoods">
	select * from goods
	where goods_price between #{minPrice} and #{maxPrice}  
</select>

这个时候不用写parameterType参数

8 使用对象作为参数

8.1 保存商品

public void save(Goods goods);
<insert id="save" parameterType="com.zpark.tea_mgr.domain.Goods">
	insert into goods(goods_id, goods_name, goods_price, goods_type)
	values(#{goodsId}, #{goodsName}, #{goodsPrice}, #{goodsType})
</insert>
try {
			GoodsMapper goodsMapper = this.sqlSession.getMapper(GoodsMapper.class);
			Goods goods = new Goods();
			goods.setGoodsName("测试用商品A");
			goods.setGoodsPrice(6666);
			goods.setGoodsNum(66);
			goods.setGoodsType(4);
			goodsMapper.save(goods);
			this.sqlSession.commit();
			System.out.println("新增商品成功");
		} catch(Exception e){
			e.printStackTrace();
			this.sqlSession.rollback();
			throw new RuntimeException(e);
		} finally{
			this.sqlSession.close();
		}

8.2 多条件查询的对象

public class GoodsSearchVO {
	private String goodsName;
	private double minPrice;
	private double maxPrice;

……

public List<Goods> findBySearchVO(GoodsSearchVO goodsSearchVO);
<select id="findBySearchVO"
        parameterType="com.zpark.tea_mgr.vo.GoodsSearchVO" resultMap="resultGoods">
	select * from goods
	where goods_name like concat('%', concat(#{goodsName}, '%'))
	and goods_price between #{minPrice} and #{maxPrice}
</select>
try {
		GoodsMapper goodsMapper 
= this.sqlSession.getMapper(GoodsMapper.class);
		GoodsSearchVO goodsSearchVO = new GoodsSearchVO("球", 100, 300);
		List<Goods> goodsList 
= goodsMapper.findBySearchVO(goodsSearchVO);
		for (Goods goods : goodsList) {
			System.out.println(goods);
		}
	} finally{
		this.sqlSession.close();
	}

8.3 使用对象封装聚合查询的结果 GoodsGroupVO

查询所有的商品的最大价格和最小价格
public class GoodsGroupVO {
	private double minPrice;
	private double maxPrice;
public GoodsGroupVO findByGroup();
<select id="findByGroup" resultType="com.zpark.tea_mgr.vo.GoodsGroupVO">
		select 
		min(goods_price) as 'minPrice',
		max(goods_price) as 'maxPrice'
		from goods
	</select>

9 MyBatis中的分页查询

9.1 SQL语句的分页查询

MySQL:  	limit 索引, 个数
Oracle:		二层子查询 + rownum

9.2 导入分页插件的jar文件

需要使用的jar文件
在这里插入图片描述

项目中的jar包
在这里插入图片描述

9.3 在MyBatis中注册分页的插件

在mybatis.xml文件中注册插件

<plugins>
	<plugin interceptor="com.github.pagehelper.PageHelper">
		<property name="dialect" value="mysql" />
	</plugin>
</plugins>

9.4 使用分页插件

分页插件使用一个静态方法设置
有效范围: 进队后面的第一个查询有效

PageHelper.startPage(1, 2);
List<Goods> goodsList = goodsMapper.findAll();
  PageHelper.startPage(int pageNum, int size);

1、 int pageNum 当前页码, 从 1 开始
2、 int size 每页记录数量

9.5 获得分页信息

比如当前页吗,总记录数量等
通过这些信息进行页面分页控制。 上一页, 下一页
在分页插件中提供了一个叫PageInfo的类,这个类封装了分页的相关信息
通过构造方法装载分页的集合对象

PageInfo<Goods> pageInfo = new PageInfo<Goods>(goodsList);

分页相关信息的方法使用

try{
			GoodsMapper goodsMapper 
= this.sqlSession.getMapper(GoodsMapper.class);
			PageHelper.startPage(1, 2);
			List<Goods> goodsList = goodsMapper.findAll();
			PageInfo<Goods> pageInfo = new PageInfo<Goods>(goodsList);
			for (Goods goods : pageInfo.getList()) {
				System.out.println(goods);
			}
			System.out.println("当前页码:" + pageInfo.getPageNum());
			System.out.println("每页记录数:" + pageInfo.getPageSize());
			System.out.println("总页码数:" + pageInfo.getPages());
			System.out.println("总记录数:" + pageInfo.getTotal());
			System.out.println("上一页:" + pageInfo.getPrePage());
			System.out.println("下一页:" + pageInfo.getNextPage());
		} finally{
			this.sqlSession.close();
		}

注意控制上一页,下一页合理范围(上一页不会 <= 0, 下一页不会 超过总页码),相关的if语句自己完成

10 关联关系映射

在MyBatis的框架中可以进行关联关系的映射,但是种类没有Hibernate那么多

10.1 只有二类关联关系

第一类: 对一 有一个实体类需要映射
第二类: 对多 有一个集合需要映射

11 对一的关联映射

11 .1数据库中关联关系

在这里插入图片描述

11.2 实体对象之间的关系

现在只处理对一的情况,所以在Goods类中有一个GoodsType类的对象

public class GoodsType {
	private int typeId;
	private String typeName;
public class Goods {
	private int goodsId;
	private String goodsName;
	private double goodsPrice;
	private int goodsNum;
	private GoodsType goodsType;

Goods类最后一个属性 设计为GoodsType类型,表明对一关系

11.3 编写Mapper接口

public interface GoodsMapper {
	public List<Goods> findAll();

11.4 编写XML文件

在这个XML文件中配置关联对象的映射,在MyBatis中有三种解决方案可选

11.4.1 第一种
直接通过对象打点调用属性的方式做映射
要求: 查询语句要使用连接查询
<!-- 第一种方案:使用连接查询 -->
	<select id="findAll" resultMap="resultGoods">
		select * from goods
		left join goods_type
		on goods_type.typeId = goods.goods_type
	</select>
	<resultMap type="com.zpark.tea_mgr.domain.Goods" id="resultGoods">
		<id property="goodsId" column="goods_id" javaType="int" />
		<result property="goodsName" column="goods_name" javaType="java.lang.String" />
		<result property="goodsPrice" column="goods_price" javaType="double" />
		<result property="goodsNum" column="goods_num" javaType="int" />
		<!-- 第一种方案:直接使用打点调用属性的方式 -->
		<result property="goodsType.typeId" column="typeId" javaType="int" />
		<result property="goodsType.typeName" column="typeName" javaType="java.lang.String" />
	</resultMap>
11.4.2 第二种

引用关联关系对象的Mapper映射
GoodsTypeMapper.xml文件

<resultMap type="com.zpark.tea_mgr.domain.GoodsType" id="resultGoodsType">
	<id property="typeId" column="typeId" javaType="int" />
	<result property="typeName" column="typeName" 
javaType="java.lang.String" />
</resultMap>

GoodsMapper.xml文件

<association property="goodsType"
	javaType="com.zpark.tea_mgr.domain.GoodsType"			resultMap="com.zpark.tea_mgr.mapper.GoodsTypeMapper.resultGoodsType" />
11.4.3 第三种

调用关联关系对象的Mapper的查询方法

public interface GoodsTypeMapper {
	public GoodsType findById(int typeId);
<select id="findById" parameterType="int" resultMap="resultGoodsType">
	select * from goods_type where typeId = #{id}
</select>

GoodsMapper.xml

<!-- 第三种方案: 查自己就好了 -->
<select id="findAll" resultMap="resultGoods">
	select * from goods
</select>
<!-- 第三种方案: 使用关联关系对象的查询的方法 -->
<association property="goodsType"
	javaType="com.zpark.tea_mgr.domain.GoodsType" 
	select="com.zpark.tea_mgr.mapper.GoodsTypeMapper.findById" 
	column="goods_type" />

12 对多的关联映射

一个类型有多个商品
设计为: 在类型类中有一个商品的集合

12.1 编写实体类

public class GoodsType {
	private int typeId;
	private String typeName;
	private List<Goods> goodsList;

12.2 编写GoodsTypeMapper接口

public interface GoodsTypeMapper {
	public List<GoodsType> findAll();

12.3 编写XML文件

映射从一个类型到多个商品

12.3.1 第一种,连接查询所有商品信息
<select id="findAll" resultMap="resultGoodsType">
		select * from goods_type
		left join goods
		on goods.goods_type = goods_type.typeId
</select>
<resultMap type="com.zpark.tea_mgr.domain.GoodsType" id="baseGoodsType">
	<id property="typeId" column="typeId" javaType="int" />
	<result property="typeName" column="typeName" 
javaType="java.lang.String" />
</resultMap>
<resultMap type="com.zpark.tea_mgr.domain.GoodsType" id="resultGoodsType" 
extends="baseGoodsType">
<collection property="goodsList" javaType="java.util.List" 
			ofType="com.zpark.tea_mgr.domain.Goods" 
			resultMap="com.zpark.tea_mgr.mapper.GoodsMapper.resultGoods"
 /> 
</resultMap>
12.3.2 第二种 调用关联关系对象的Mapper的查询方法
public interface GoodsMapper {
	public List<Goods> findByType(int goodsTypeId);
<select id="findByType" parameterType="int" resultMap="resultGoods">
	select * from goods where goods_type = #{id}
</select>
<!-- 第二种方案 --> 
<collection property="goodsList" javaType="java.util.List" 
		ofType="com.zpark.tea_mgr.domain.Goods"
		select="com.zpark.tea_mgr.mapper.GoodsMapper.findByType" 
		column="typeId" />

13 开发环境应用方案

13.1 不要使用双向映射

13.2 针对一个对象的映射,使用连接查询

13.3 针对一个集合的映射,不要再MyBatis的Mapper文件中映射

** 但要提供查询的方法,在业务层完成组装**

14 映射案例 ---- 最佳解决方案

14.1 编写实体类

public class Goods implements Serializable{
	private static final long serialVersionUID = 8874153057031505335L;
	private Integer goodsId;
	private String goodsName;
	private Double goodsPrice;
	private Integer goodsNum;
	private GoodsType goodsType;
public class GoodsType {
	private Integer typeId;
	private String typeName;
	private List<Goods> goodsList;

14.2 编写Mapper接口

public interface GoodsMapper {
	public List<Goods> findAll();
	/**
	 * 给关联关系对象(商品类型)提供查找其下商品的方法
	 * 如果要查某个商品类型信息的时候要带出相关的商品信息
	 * @param typeId 某个商品类型的ID
	 * @return 返回某个商品类型下的商品集
	 */
	public List<Goods> findByType(int typeId);
public interface GoodsTypeMapper {
	public List<GoodsType> findAll(); 
	public GoodsType findById(int typeId);

14.3 编写XML文件

14.3.1 编写GoodsMapper.xml文件

针对对象在编写查询语句时,直接使用连接查询

<select id="findAll" resultMap="BaseResultMap">
		select * from goods
		left join goods_type
		on goods_type.typeId = goods.goods_type
</select>
<select id="findByType" parameterType="java.lang.Integer"
resultMap="BaseResultMap">
		select * from goods
		left join goods_type
		on goods_type.typeId = goods.goods_type
		where goods_type = #{id}
</select>

编写映射时直接关联关系对象的resultMap映射

<resultMap type="com.zpark.tea_mgr.domain.Goods" id="BaseResultMap">
	<id column="goods_id" property="goodsId" jdbcType="INTEGER" />
	<result column="goods_name" 
property="goodsName" jdbcType="VARCHAR" />
	<result column="goods_price" property="goodsPrice" jdbcType="DOUBLE" />
	<result column="goods_num" property="goodsNum" jdbcType="INTEGER" />
	<association property="goodsType"
javaType="com.zpark.tea_mgr.domain.GoodsType"			 resultMap="com.zpark.tea_mgr.mapper.GoodsTypeMapper.BaseResultMap" />
</resultMap>
14.3.2 编写GoodsTypeMapper.xml文件

针对集合,不用连接查询集合的数据

<select id="findAll" resultMap="BaseResultMap">
	select * from goods_type
</select>
<select id="findById" parameterType="java.lang.Integer"
       resultMap="BaseResultMap">
	select * from goods_type
	where typeId = #{id}
</select>

针对集合映射时,不要映射集合

<resultMap type="com.zpark.tea_mgr.domain.GoodsType" id="BaseResultMap">
	<id property="typeId" column="typeId" javaType="java.lang.Integer" />
	<result column="typeName" property="typeName" jdbcType="VARCHAR" />
</resultMap>

14.4 编写service层

public class GoodsTypeService {
	public GoodsType findById(int typeId){
		SqlSession sqlSession = null;
		try{
			String resource = "mybatis.xml";
			Reader reader = Resources.getResourceAsReader(resource);
			SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
			sqlSession = ssf.openSession();
			GoodsTypeMapper goodsTypeMapper =
 sqlSession.getMapper(GoodsTypeMapper.class);
			GoodsType goodsType = goodsTypeMapper.findById(typeId);
			GoodsMapper goodsMapper =
 sqlSession.getMapper(GoodsMapper.class);
			List<Goods> goodsList = goodsMapper.findByType(typeId);
			// 组装
			goodsType.setGoodsList(goodsList);
			return goodsType;
		}catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);
		}finally{
			sqlSession.close();
		}
	}
}

14.5 测试

15 动态SQL

15.1 set标签在update语句中的使用

public interface GoodsMapper {
	public void update(Goods goods);
	public Goods findById(int goodsId);
	public void updateByDynamicSQL(Goods goods);
<update id="updateByDynamicSQL"
              parameterType="com.zpark.tea_mgr.domain.Goods">
		update goods
		<set>
			<if test="goodsName != null">
				goods_name = #{goodsName},
			</if>
			<if test="goodsPrice != null">
				goods_price = #{goodsPrice},
			</if>
			<if test="goodsNum != null">
				goods_num = #{goodsNum},
			</if>
			<if test="goodsType != null and goodsType.typeId != null">
				goods_type = #{goodsType.typeId},
			</if>
		</set>
		where goods_id = #{goodsId}
	</update>

使用动态SQL,我们要修改商品,可以不必先从数据库中查询出来

15.2 where标签在查询语句中的使用

public class GoodsSearchVO {
	private String goodsName;
	private Double minPrice;
	private Double maxPrice;
public List<Map<String, Object>> findBySearchVO(GoodsSearchVO goodsSearchVO);
<select id="findBySearchVO"
parameterType="com.zpark.tea_mgr.vo.GoodsSearchVO"
	        resultType="java.util.Map">
		select
		goods_name as 'goodsName',
		goods_price as 'goodsPrice',
		goods_num as 'goodsNum',
		typeName as 'typeName'
		from goods
		left join goods_type
		on goods_type.typeId = goods.goods_type
		<where>
			<if test="goodsName != null">
				goods_name like concat('%', #{goodsName}, '%')
			</if>
			<if test="minPrice != null">
				and goods_price &gt; #{minPrice}
			</if>
			<if test="maxPrice != null">
				and goods_price &lt; #{maxPrice}
			</if>
		</where>
	</select>

15.3 foreach标签的使用

批量插入

public void saveBat(List<Goods> goodsList);
<insert id="saveBat" parameterType="java.util.List">
	insert into goods (goods_name, goods_price, goods_num, goods_type)
	values
	<foreach collection="list" item="goods" separator=",">
		(#{goods.goodsName}, #{goods.goodsPrice}, #{goods.goodsNum},
#{goods.goodsType.typeId})
	</foreach>
</insert>

批量删除

public void delBat(List<Integer> seq);
<delete id="delBat" parameterType="java.util.List">
	delete from goods
	where goods_id in 
	<foreach collection="list" item="id" separator="," open="(" close=")"
 index="index">
		#{id}
	</foreach>
</delete>

16 MyBatis 整合 Spring

16.1 Spring 整合MyBatis框架时

1.spring抢MyBatis的连接
2 Spring抢Mapper接口
3 spring抢Mapper.xml文件

16.2 创建工程并导入jar包

导入MyBatis框架

在这里插入图片描述

导入Spring框架

在这里插入图片描述

16.3 Spring抢MyBatis的连接

1 MyBatis的配置文件中不用写连接参数
在这里插入图片描述

2 在applicationContext.xml文件中配置数据源
在这里插入图片描述

3配置一个MyBatis的sqlSessionFactory
在这里插入图片描述

16.4 Spring抢Mapper.xml文件

在这里插入图片描述

16.5 Spring配置事务处理对象

在这里插入图片描述

16.6 编写实体类

16.7 编写Mapper接口

@Repository("GoodsMapper")
public interface GoodsMapper {
	public List<Goods> findAll();
	public void save(Goods goods);
}

Mapper.xml文件没有什么改动,这里不再提供了

@Repository("GoodsTypeMapper")
public interface GoodsTypeMapper {

16.8 编写业务层 GoodsService

@Service("GoodsService")
public class GoodsService {
	
	@Autowired
	@Qualifier("GoodsMapper")
	private GoodsMapper goodsMapper;
	
	public GoodsMapper getGoodsMapper() {
		return goodsMapper;
	}

	public void setGoodsMapper(GoodsMapper goodsMapper) {
		this.goodsMapper = goodsMapper;
	}

	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List<Goods> findAll(){
		try{
			return this.goodsMapper.findAll();
		}catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	@Transactional(propagation = Propagation.REQUIRED, 
rollbackFor = { Exception.class })
	public void save(Goods goods){
		try{
			this.goodsMapper.save(goods);
			System.out.println("保存成功!");
		}catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
}

16.9 测试

							Albert.Zhou.CH总结 前辈经验于此,与各位分享
												2019-03-20

-------------------------------To be continued------------------------------

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Review-MyBatis 的相关文章

随机推荐

  • 勇于尝试新鲜事物,利于项目来积累学习经验

    很多人都会根据企业的发展需求 再选择自己的开发方向 其实没必要完全根据企业的发展路线来决定的个人的职业路线 正如 黑客与画家 和 黑客帝国 所表达的 程序员应该将白天的工作作为一种职业相关性的经验积累 而将晚上的时间用于尝试新的技术和领域
  • matlab 学习算法,matlab深度学习算法合集

    实例简介 CAE CNN NN SAE等等matlab版深度学习算法合集 以及相关测试数据 拿到就能直接用 实例截图 核心代码 DeepLearnToolbox matlab DeepLearnToolbox CAE caeapplygra
  • java中空值怎么表示_JAVA中空值null与字符串null含义的区分

    java中字符串型的量 如 String s 初始化为空时 s null 打印出来为null 但是对他不能进行 isEmpty 和 length 的操作 会抛出空指针异常 给他们后边添加字符串后 s s yuanyuan 打印时前边会保留n
  • 2019年全国一二线城市程序员工资大调查

    我在4月1日到3日之间 抓取了某招聘网站的软件和互联网类招聘数据40万条 其中通过程序判断为程序员的14万条 地域方面 我选择了24个主要城市 这里的程序员包括普通程序员 架构师和算法工程师 美工等不计算在内 这点和2017年不同 如果你只
  • ftp

    1 ftp上传文件 1 1相关依赖
  • OpenMMLab_0【简介】

    1 项目动机 统一的深度学习框架 统一的算法框架和生态 自2018年开源以来已经能够实现很多算法 2 总体现状 3 总体框架概览 3 1 算法训练 部署一体化 3 2 算法框架介绍 MMDetection MMDetection3D 7 个
  • Bootstrap入门(一)

    前言 大家好 我是九歌 今天我要分享的内容是Bootstrap的入门 首先老规矩先上思维导图 提示 以下是本篇文章正文内容 下面案例可供参考 一 Bootstrap 学习一门新的技术我们终究都逃不过三个W What Why Where 1
  • Vue3.0

    teleport Teleport 提供了一种干净的方法 允许我们控制在 DOM 中哪个父节点下呈现 HTML 而不必求助于全局状态或将其拆分为两个组件
  • 《C++ Primer》学习笔记(十五):面向对象编程

    C Primer 学习笔记 十五 面向对象编程 抽象基类 访问控制与继承 构造函数与拷贝控制 文本查询程序再探 练习 面向对象编程的核心思想是数据抽象 继承和动态绑定 在C 语言中 当我们使用基类的引用 或指针 调用一个虚函数时将发生动态绑
  • python跟易语言的爬虫_用易语言写个简单的小爬虫其中的关键点

    一 请求头 ctrl L快捷键创建变量 变量名 类型 协议参数 类 POST数据类 请求头数据 文本型 协议参数 添加 v 4 52 0 请求头数据 协议参数 获取协议头数据 二 请求参数比如post 变量名 类型 请求data参数 类 P
  • 【负荷预测】基于神经网络的负荷预测和价格预测(Matlab代码实现)

    目录 1 概述 2 基于神经网络的负荷预测 Matlab实现 2 1 代码 2 2 结果 2 3 回归树模型的进一步改进 3 基于神经网络的价格预测 Matlab代码实现 4 阅读全文 Matlab代码 1 概述 这个例子演示了用MATLA
  • 《软件调试的艺术》学习笔记——GDB使用技巧摘要(3)——程序崩溃处理

    程序为什么会崩溃 内存中的程序布局 当某个错误导致程序突然和异常地停止执行时 程序崩溃 迄今为止最为常见的导致程序崩溃的原因是试图在未经允许的情况下访问一个内存位置 硬件会感知这件事 并执行对操作系统的跳转 Unix系列的平台上 操作系统一
  • VS2015下用Qt Designer创建对话框

    目录 1 Qt Designer新建文件 选择适合的模板 布局窗口 2 在右侧属性窗口修改名称为需要的名称 3 文件另存为对象名称一样的xxx ui文件 4 创建xxx cpp和xxx h文件 加入工程 也可以在qt creator中创建
  • sql-labs闯关38~45

    sql labs闯关38 45 友善爱国平等诚信民主友善爱国爱国友善平等诚信自由平等友善平等法治诚信民主民主 复习笔记1 内容 sql labs第38关 GET请求 堆叠查询注入 字符型 sql labs第39关 GET请求 堆叠查询注入
  • 30分钟从零开始搭建并部署个人知识库(超详细)

    前言 网上关于动态文档生成工具有很多如 Docsify VuePress Docute Hexo这些都是一些非常优秀的文档生成工具 本章主要介绍如何快速使用Docsify搭建一个快捷 轻量级的个人 团队文档 并且通过Github Pages
  • dracut 基本介绍

    dracut 基本介绍 dracut 维基 https dracut wiki kernel org index php Main Page http www 360doc com content 13 0428 09 12139495 2
  • 计算机网络系列五 -- 运输层详解

    1 运输层 1 1 运输层的定义 运输层是 OSI 七层参考模型的第四层 主要功能为应用层提供通信服务 它即是面向通信的最高层 也是用户功能的最底层 在计算机网络中 真正进行数据通信的是两个主机的进程 由于一个主机中有多个进程同时在通信 而
  • vc++画线段的函数_word2vec的损失函数

    虽然word2vec常被当作无监督 但是其训练过程跟有监督基本差不多 原始的word2vec暂时不考虑负采样和huffman tree 其损失函数就是多元交叉熵 多元交叉熵的公式 以传统机器学习来说 这里的Zj就是某个类别的预测概率 yj
  • 物联网嵌入式学习路线发展方向(表格一目了然)

    文章目录 一 学习路线 二 各种分类 1 软件硬件分类 2 发展方向 技术类型 对应岗位分类 2 1 芯片方向 2 2 Linux方向 3 常见板子芯片内核 4 嵌入式公司 对于小白 不知道嵌入式整个体系 学什么 顺序是什么 可以找什么工作
  • Review-MyBatis

    MyBatis 1 学习方法 MyBatis框架功能与Hibernate一样 都是持久化框架 都是操作JDBC 做ORM框架 1 MyBatis框架比Hibernate小 2 做的是针对SQL语句查询结果进行封装 2 MyBatis框架是什