- 使用mybatis需要添加mybatis的依赖,同时由于mybatis在是对jdbc的封装,也需要引入对应数据库的jdbc依赖
- 配置mybatis,在resources目录下创建一个mybatis-config.xml文件,然后输入以下类容(可以在官网上找到配置类容链接)
- 创建SqlSession,mybatis对于数据库的操作需要依赖于SqlSession对象。
SqlSession session = null;
try {
Reader reader = Resources.getResourceAsReader("mybatis-conf.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
session = factory.openSession();
Connection connection = session.getConnection();
System.out.println(connection);
}catch (Exception e){
e.printStackTrace();
}finally {
if(session != null)
session.close();
}
二、执行crud
mybatis是对JDBC的封装,在JDBC中SQL语句与代码混在一起,mybatis实现了业务逻辑代码与SQL语句的解耦。所有的SQL语句都写在xml文件中,session对象负责执行这些SQL语句并且进行封装。在resources目录下新建mappers文件夹,在里面新建xml文件用来保存SQL语句。可以从官网上粘贴对应的dtd,所有的SQL语句都书写在mapper标签内,其中namespace指定当前xml文件的命名空间,需要注意的是这些语句是根据namespace和namespace里面语句的id来区分的。
- 查询
select * from t_goods
执行查询语句
@Test
public void testReturnMap(){
SqlSession session = null;
try {
session = MyBatisUtil.openSession();
List
对于查询语句的返回结果,mybatis可以直接将结果包装成的实体对象,这个实体对象中不应该包含自定义的对象。查询语句可能输入参数,可以只传入一个参数,也可以使用Map对象
实体类:
package com.zyf.mybatis.Entity;
import java.io.Serializable;
public class Goods implements Serializable {
private Integer goodsId;
private String title;
private String subTitle;
private Float originalCost;
private Float currentPrice;
private Float discount;
private Integer isFreeDelivery;
private Integer categoryID;
public Goods() {
}
public Goods(String title, String subTitle, Float originalCost, Float currentPrice, Float discount, Integer isFreeDelivery, Integer categoryID) {
this.title = title;
this.subTitle = subTitle;
this.originalCost = originalCost;
this.currentPrice = currentPrice;
this.discount = discount;
this.isFreeDelivery = isFreeDelivery;
this.categoryID = categoryID;
}
public Integer getGoodsId() {
return goodsId;
}
public String getTitle() {
return title;
}
public String getSubTitle() {
return subTitle;
}
public Float getOriginalCost() {
return originalCost;
}
public Float getCurrentPrice() {
return currentPrice;
}
public Float getDiscount() {
return discount;
}
public Integer getIsFreeDelivery() {
return isFreeDelivery;
}
public Integer getCategoryID() {
return categoryID;
}
public void setGoodsId(Integer goodsId) {
this.goodsId = goodsId;
}
public void setTitle(String title) {
this.title = title;
}
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public void setOriginalCost(Float originalCost) {
this.originalCost = originalCost;
}
public void setCurrentPrice(Float currentPrice) {
this.currentPrice = currentPrice;
}
public void setDiscount(Float discount) {
this.discount = discount;
}
public void setIsFreeDelivery(Integer isFreeDelivery) {
this.isFreeDelivery = isFreeDelivery;
}
public void setCategoryID(Integer categoryID) {
this.categoryID = categoryID;
}
@Override
public String toString() {
return this.getGoodsId()+"-"+this.getTitle()+"-"+this.getSubTitle()+"-"+this.getOriginalCost()+
"-"+this.getCurrentPrice()+"-"+this.getDiscount()+"-"+this.getIsFreeDelivery()+"-"+
this.getCategoryID();
}
}
查询语句:
执行查询语句:
@Test
public void testSelectById(){
SqlSession session = null;
try {
session = MyBatisUtil.openSession();
Goods goods = session.selectOne("goods.selectById", 5739);
System.out.println(goods);
}catch (Exception e){
e.printStackTrace();
}finally {
if(session != null)
session.close();
}
}
@Test
public void testSelectByPrice(){
SqlSession session = null;
try {
session = MyBatisUtil.openSession();
Map map = new HashMap();
map.put("min" , 500);
map.put("max", 1000);
List goods = session.selectList("goods.selectByPrice", map);
System.out.println(goods);
}catch (Exception e){
e.printStackTrace();
}finally {
if(session != null)
session.close();
}
}
对于简单的对象(属性中不包含自定义对象),mybatis可以进行自定义的封装,对于复杂的对象,需要通过resultMap来指定表的列和对象的映射规则。
实体对象:
package com.zyf.mybatis.dto;
import com.zyf.mybatis.Entity.Goods;
public class GoodsDTO {
private Goods goods;
private String categoryName;
public Goods getGoods() {
return goods;
}
public void setGoods(Goods goods) {
this.goods = goods;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
@Override
public String toString() {
return "GoodsDTO{" +
"goods=" + goods +
", categoryName='" + categoryName + ''' +
'}';
}
}
xml文件:
select g.*, t.category_name from t_goods g, t_category t where g.category_id = t.category_id
执行查询语句的方式与前面相同。
- 插入
插入语句一般传入实体对象,然而参入实体对象时我们一般不设置主键,而是使用SQL语句或者使用自增主键来产生。我们可以将生成的主键回填到体对象。对于支持自增主键的数据库,我们可以使用useGeneratedKeys,对于不支持自增主键的数据库我们需要使用selectKey 来产生主键并将值放入到数据库中。
select -6 insert into t_goods(title, sub_title, original_cost, current_price,discount, is_free_delivery, category_id) values(#{title}, #{subTitle}, #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryID})insert into t_goods(title, sub_title, original_cost, current_price,discount, is_free_delivery, category_id) values(#{title}, #{subTitle}, #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryID})
- 删除
delete from t_goods where goods_id = #{value}
- 修改
update t_goods set title = #{title}, sub_title = #{subTitle}, original_cost = #{originalCost}, current_price = #{currentPrice}, discount = #{discount}, is_free_delivery = #{isFreeDelivery}, category_id = #{categoryID} where goods_id = #{goodsId}
- 关联查询
一个学生对应着唯一一个班级,一个班级对应着多个学生。这分别对应着多对一和一对多关系。可以使用关联查询来实现这个效果。
一个GoodsGoodsDetail 对象对应着一个Goods对象
public class GoodsDetail {
private Integer gdId;
private Integer goodsId;
private String gdPicUrl;
private Integer gdOrder;
private Goods goods;
}
多对一可以使用之前的resultMap实现,这里有更简单的方法(之前的复杂对象查询也可以使用这个方法)。
编写xml文件
新建goodsDetail.xml文件,并且设置其命名空间为goodsDetail。
select * from t_goods_detail where goods_id = #{value} select * from t_goods_detail limit 9,10
一个Goods对应着多个GoodsDetail对象
public class Goods implements Serializable {
private Integer goodsId;
private String title;
private String subTitle;
private Float originalCost;
private Float currentPrice;
private Float discount;
private Integer isFreeDelivery;
private Integer categoryID;
private List goodsDetails;
}
在goods.xml文件中添加
三、动态SQLselect * from t_goods limit 1,10
mybatis支持使用,,等标签动态生成SQL语句
四、mybatis中的二级缓存select * from t_goods and current_price ">> #{min} and current_price < #{max}
执行查询语句时,mybatis需要对数据库中的数据进行读取,开销大,通过将之前的查询结果存放在内存中可以加速提高查询速度节省系统开销。mybatis支持二级缓存,默认情况下自动开启一级缓存,开启二级缓存时需要进行一定的配置。
- 一级缓存
一级缓存的范围是一次session,在这个session中执行的查询语句的结果都会被放入当前session的一个缓冲区中,当再次查询之前的查询结果时会从缓冲区中读取这个对象。这个缓冲区别的session无法访问。 - 二级缓存
开启二级缓存后,一个namespace中的查询语句产生的结果会被放在一个缓冲区中,当再次查询当前缓冲区中的对象时会直接去缓冲区中取。
二级缓存需要手动开启,在标签下添加。其中eviction指定缓存的清除策略(相当于操作系统中进程的调度策略)。flushInterval指定缓存区的刷新时间,过了指定时间清除缓存。size设置缓存的大小(单位是对象,如果查询结果是一个集合则这个集合视为一个对象)。readOnly设置缓存区是否是只读,如果设置为true则获取是缓存中的对象,如果设置为false则返回的是缓存对象的拷贝。 - 缓冲的清空
对于一级缓存,只要执行了commit就会清空缓存。对于二级缓存,执行了update,delete或者insert语句后再执行commit才会清空缓存。
可以手动设置执行某条语句后清空缓存,在执行语句中添加flushCache=“true”,如:
select * from t_goods where goods_id = #{value}
- 不放入缓冲区
对于查询结果为集合的语句,这个集合被设为一个对象存放在缓冲区中,只有在查询结果与这个集合中的所有内容都相同时才会去缓冲区中取这个集合,命中率较低,因此可以设置某条查询语句的查询结果不放入缓冲区中,使用useCache=“false”,这个貌似不对一个session起作用。
五、pagehelperselect * from t_goods where current_price between #{min} and #{max}
pagehelper是国人开发的一款分页插件,网址https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md。使用前需要添加pagehelper和jsqlparser依赖,然后在mybatis的配置文件中设置使用pagehelper的拦截器,在标签内添加(需要注意添加的位置,放在标签之后,具体的顺序可以查看官网)。
使用pagehelper
//设置业的大小为10并且查询第2页的数据 PageHelper.startPage(2, 10); Page六、使用C3P0连接池page = (Page)session.selectList("goods.selectAll"); List list = page.getResult();
首先添加c3p0的依赖(groupId为com.mchange),编写类
package com.zyf.mybatis.datasource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
public class C3PODataSourceFactory extends UnpooledDataSourceFactory {
public C3PODataSourceFactory(){
//使用C3P0的数据源
this.dataSource = new ComboPooledDataSource();
}
}
修改配置文件
七、批处理//之前使用的配置,注意这里的dataSource 类型为POOLED,这也是为什么前面编写的类继承UnpooledDataSourceFactory //使用C3P0数据源时的配置
JDBC支持批处理,在mybatis可以动态生成SQL语句来执行批量删除、插入。
批量删除:
delete from t_goods where goods_id in #{item}
批量更新
八、基于注解编写SQL语言insert into t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id) values (#{item.title}, #{item.subTitle}, #{item.originalCost}, #{item.currentPrice}, #{item.discount}, #{item.isFreeDelivery}, # {item.categoryID})
基于注解编写SQL语言需要先建立一个借口,然后在接口的方法上添加注解。在执行查询时(要在mybatis的配置文件中开启对这个接口的扫描。用啦扫描某个mapper文件,用来扫描接口, 使用查询语句: 使用插入语句 对复杂查询结果进行映射需要使用@Results注解@Test
public void testSelectByPrice(){
SqlSession session = null;
try {
session = MyBatisUtil.openSession();
GoodsDAO goodsDAO = session.getMapper(GoodsDAO.class);
List
@Test
public void testInsert(){
SqlSession session = null;
try {
session = MyBatisUtil.openSession();
Goods goods = new Goods("三鹿奶粉", "国产", (float) 699, (float) 699, (float) 1, 1, 21);
GoodsDAO dao = session.getMapper(GoodsDAO.class);
dao.insert(goods);
System.out.println(goods);
}catch (Exception e){
e.printStackTrace();
}finally {
if(session != null)
session.close();
}
}
@Select("select g.*, c.* from t_goods g, t_category c where g.category_id = c.category_id")
@Results({
@Result(column = "goods_id", property = "goods.goodsId", id = true),
@Result(property="goods.title", column="title"),
@Result(property="goods.subTitle", column="sub_title" ),
@Result(property="goods.originalCost", column="original_cost"),
@Result(property="goods.currentPrice", column="current_price" ),
@Result(property="goods.discount", column="discount"),
@Result(property="goods.isFreeDelivery", column="is_free_delivery" ),
@Result(property="goods.categoryID", column="category_id")
})
List



