栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MyBatis

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MyBatis

MyBatis 一.原生态jdbc编程中的问题总结 1.创建mysql数据

导入下边的脚本:

sql_table.sql:记录表结构

sql_data.sql:记录测试数据,在实际企业开发中,最后提供一个初始化数据脚本

2.原生态jdbc程序

使用jdbc查询mysql数据库中用户表的记录。

修改pom.xml,引入相关依赖


  mysql
  mysql-connector-java
  8.0.15
 

程序代码:JdbcTest.java使用jdbc的原始方法(未经封装)实现了查询数据库表记录的操作

public class JdbcTest {

	public static void main(String[] args) {

		Connection connection = null;

		PreparedStatement preparedStatement = null;

		ResultSet resultSet = null;

		try {

			Class.forName("com.mysql.jdbc.Driver"); // 加载数据库驱动

			// 通过驱动管理类获取数据库链接

			connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/order?characterEncoding=utf-8", "root", "root");

			String sql = "select  from user where username = ?"; // 定义sql语句 ?表示占位符

			preparedStatement = connection.prepareStatement(sql); // 获取预处理statement

			// 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值

			preparedStatement.setString(1, "王五");

			resultSet = preparedStatement.executeQuery();// 向数据库发出sql执行查询,查询出结果集

			while (resultSet.next()) { // 遍历查询结果集

				System.out.println(resultSet.getString("id") + "  " + resultSet.getString("username"));

			}

		} catch (Exception e) {

			e.printStackTrace();

		} finally {

			// 释放资源

			if (resultSet != null) {

				try {

					resultSet.close();

				} catch (SQLException e) {

					e.printStackTrace();

				}

			}

			if (preparedStatement != null) {

				try {

					preparedStatement.close();

				} catch (SQLException e) {

					e.printStackTrace();

				}

			}

			if (connection != null) {

				try {

					connection.close();

				} catch (SQLException e) {

					e.printStackTrace();

				}

			}

		}

	}

}
3.问题总结

1)、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。

设想:使用数据库连接池管理数据库连接。

2)、将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护。

设想:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。

3)、向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。

设想:将sql语句及占位符号和参数全部配置在xml中。

4)、从ResultSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护。

设想:将查询的结果集,自动映射成java对象。

二.mybatis框架原理 1.mybatis是什么?

​ mybatis是一个持久层的框架,是apache下的顶级项目。mybatis托管到goolecode下,再后来托管到github下(https://github.com/mybatis/mybatis-3/releases)。

​ mybatis让程序员将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。 mybatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)

2.mybatis框架原理

1、 mybatis配置

SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xRpLBkD3-1641215111304)(image/wpsPLJvK4.png)]

三.mybatis入门程序 1.工程结构 1.1 需求

根据用户id(主键)查询用户信息

根据用户名称模糊查询用户信息

添加用户

删除用户

更新用户

1.2 修改pom.xml,引入相关依赖

  org.mybatis
  mybatis
  3.4.6

1.3 新建log4j.properties日志属性文件

mybatis默认使用log4j作为输出日志信息。

在src文件夹下,创建了resources文件夹,右击选择Mark Directory as --> resources root,在其里面创建log4j.properties文件如下:

# Global logging configuration
# 在开发环境下日志级别要设置成DEBUG,生产环境设置成info或error
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

修改pom.xml,添加日志依赖


  log4j
  log4j
  1.2.17

1.4 新建db.properties属性文件
#mysql
db.username = root
db.password = root
db.jdbcUrl = jdbc:mysql://localhost:3306/order?characterEncoding=utf-8
db.driverClass = com.mysql.jdbc.Driver

修改pom.xml,添加mysql依赖


    mysql
    mysql-connector-java
    5.1.38

1.5 SqlMapConfig.xml核心配置文件

SqlMapConfig.xml是mybatis核心配置文件,配置mybatis的运行环境,数据源、事务等。

在src文件夹下,创建了resources文件夹,在其里面创建SqlMapConfig.xml文件。

首先,先创建mybatis核心配置文件模版

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-15WQGLpl-1641215111309)(image/image-20200713211001576.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sisJam0u-1641215111310)(image/image-20200713211254836.png)]






要求核心配置文件中,configuration所有配置必须严格按照以下顺序进行编写。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5vGnbLOq-1641215111311)(image/image-20210624155159869.png)]

其次,再新建SqlMapConfig.xml核心配置文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L9pu2OGi-1641215111311)(image/image-20200713211431635.png)]




	
  	
    

    
    

    
    
        
    

    
    
        
            
            
            
            
            
                
                
                
                
            
        
    


    
    
        
    
  


1.6 Mapper映射文件

若想在与同名接口同路径下创建Mapper映射文件,需要修改pom.xml。

原因是IDEA编译后默认会把resources下的文件放到target的classpath下,但是src下的只有Java文件编译生成.class文件放入classpath下,其他文件会忽略的,例如.xml文件。


  
  
    
      src/main/java
      
        **
public interface UserMapper {
    //通过id查询用户信息
    public User selectUserById(Integer id);
}

2.4 在SqlMapConfig.xml中加载映射文件

在sqlMapConfig.xml中加载User.xml:

 

  


2.5 新建junit测试类

1). 修改test目录,右击选择Mark Directory as -> Test Resources Root

2). 选择需要建junit测试类的接口,右击选择Go To -> Test

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vs8rMXxE-1641215111316)(image/image-20200713221414296.png)]

3). 创建UserMapperTest类,勾选需要测试的方法

4). 编写测试类

public class UserMapperTest {

  	//创建会话工厂对象
    private SqlSessionFactory factory;

    @Before
    public void setUp() throws Exception {
      	//加载mybatis核心配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void selectUserById() {
        SqlSession sqlSession = factory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.selectUserById(1);
        System.out.println(user);
        sqlSession.close();
    }
  
}

3.根据用户名称模糊查询用户信息 3.1 修改映射文件UserMapper.xml


select  from user where id=#{id} and username like '%${username}%'



上边的#{id}、%${username}% 是hashmap的key。

2.2 测试
Public void testFindUserByHashmap()throws Exception{
		//获取session
		SqlSession session = sqlSessionFactory.openSession();
		//获限mapper接口实例
		UserMapper userMapper = session.getMapper(UserMapper.class);
		//构造查询条件Hashmap对象
		HashMap map = new HashMap();
		map.put("id", 1);
		map.put("username", "小明");
		
		//传递Hashmap对象查询用户列表
		Listlist = userMapper.findUserByHashmap(map);
		//关闭session
		session.close();
	}

异常测试:

传递的map中的key和sql中解析的key不一致。

测试结果没有报错,只是通过key获取值为空。

六.输出映射-resultType及resultMap 1.resultType

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。

如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。

只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

1.1 输出简单类型 1.1.1 需求

用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页。

1.1.2 mapper.xml

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NzyfRgsh-1641215111325)(image/wps21.jpg)]

1.1.3 mapper.java

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L5vH7HYy-1641215111325)(image/wps22.jpg)]

1.1.4 测试代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n7Nv1S4e-1641215111326)(image/wps23.jpg)]

1.1.5 小结

查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。

1.2 输出pojo对象和pojo列表

不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的。

在mapper.java指定的方法返回值类型不一样:

1.2.1 输出单个pojo对象,方法返回值是单个对象类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z6ZKQkVr-1641215111326)(image/wps24.jpg)]

1.2.2 输出pojo对象list,方法返回值是List

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiaEpQBF-1641215111327)(image/wps25.jpg)]

生成的动态代理对象中是根据mapper.java中的方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用 ).

2.resultMap

mybatis中使用resultMap完成高级输出结果映射。

2.1 resultMap使用方法

如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

1、定义resultMap

2、使用resultMap作为statement的输出映射类型

2.2 将下边的sql使用User完成映射

SELECT id a , username b FROM USER WHERe id=#{value} User类中属性名和上边查询列名不一致。

2.2.1定义resultMap

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0yTObHD6-1641215111327)(image/wps26.jpg)]

2.2.2 使用resultMap作为statement的输出映射类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61qb2TlH-1641215111327)(image/wps27.jpg)]

2.2.3 mapper.java

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pjp4nTgM-1641215111328)(image/wps28.jpg)]

2.2.4 测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vU4nDi4Z-1641215111330)(image/wps29.jpg)]

3. 小结

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

七.动态sql 1.什么是动态sql?

mybatis核心对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装。

2.什么是sql片段?

将实现的动态sql的代码块抽取出来,组成一个sql片段。其它的statement中就可以引用sql片段,方便程序员进行开发。

3.需求
1.需求:通过用户性别和姓名查询用户列表 PS:不允许性别或者姓名为null或者空串

2.需求:通过用户性别和姓名查询用户列表条数 PS:不允许性别或者姓名为null或者空串

3.需求:通过用户性别和姓名查询用户列表,且id值是15或20或25  PS:不允许性别或者姓名为null或者空串

4.编写UserCustom类
public class UserCustom extends User{

}

5.编写UserQueryVO类
public class UserQueryVO {

    private UserCustom userCustom;

    private List ids;

    public UserCustom getUserCustom() {
        return userCustom;
    }

    public void setUserCustom(UserCustom userCustom) {
        this.userCustom = userCustom;
    }

    public List getIds() {
        return ids;
    }

    public void setIds(List ids) {
        this.ids = ids;
    }

}

6.编写UserMapper.xml映射文件





    
    
        
            
                and sex = #{userCustom.sex}
            
            
                and username like concat('%',#{userCustom.username},'%') 
            
        
    

    
    
        

            
            
            
                id=#{user_id}
            

            
            
        
    

    
    
        select * from user 
        
            
        
    

    
    
        select * from user
        
            
            
        
    



7.编写UserMapper.java接口
import com.cm.entity.UserCustom;
import com.cm.entity.UserQueryVO;

import java.util.List;

public interface UserMapper {

    public List selectList(UserQueryVO vo);

    public int selectCount(UserQueryVO vo);

    public List selectByIds(UserQueryVO vo);

}

8.在核心配置文件中添加扫描

  


9.测试
public class UserMapperTest {
    private SqlSessionFactory factory;

    @Before
    public void setUp() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void selectList() {
        SqlSession sqlSession = factory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        UserCustom userCustom = new UserCustom();
        userCustom.setSex("1");
        userCustom.setUsername("明");
        UserQueryVO vo = new UserQueryVO();
        vo.setUserCustom(userCustom);
        List list = userMapper.selectList(vo);
        for (UserCustom user: list) {
            System.out.println(user);
        }
        sqlSession.close();
    }

    @Test
    public void selectCount() {
        SqlSession sqlSession = factory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        UserCustom userCustom = new UserCustom();
        userCustom.setSex("1");
        userCustom.setUsername(null);
        UserQueryVO vo = new UserQueryVO();
        vo.setUserCustom(userCustom);
        int count = userMapper.selectCount(vo);
        System.out.println(count);
        sqlSession.close();
    }

    @Test
    public void selectByIds() {
        SqlSession sqlSession = factory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        UserCustom userCustom = new UserCustom();
        userCustom.setSex("");
        userCustom.setUsername("明");
        List ids = new ArrayList<>();
        ids.add(15);
        ids.add(20);
        ids.add(25);
        UserQueryVO vo = new UserQueryVO();
        vo.setUserCustom(userCustom);
        vo.setIds(ids);
        List list = userMapper.selectByIds(vo);
        for (UserCustom user: list) {
            System.out.println(user);
        }
        sqlSession.close();
    }
}

八.高级映射 1.分析订单商品数据模型 1.1 每张表记录的数据内容

分模块对每张表记录的内容进行熟悉,相当于你学习系统需求(功能)的过程。

用户表:user

​ 记录了购买商品的用户信息

订单表:orders

​ 记录了用户所创建的订单(购买商品的订单)

订单明细表:orderdetail

​ 记录了订单的详细信息即购买商品的信息

商品表:items

​ 记录了商品信息

1.2 每张表重要的字段设置

非空字段、外键字段

1.3 数据库级别表与表之间的关系
外键关系:

1).外键user_id所在的表orders叫做子表;通过外键user_id指向主表(父表)user中的id

2).外键orders_id所在的表orderdetail叫做子表;通过外键orders_id指向主表(父表)orders中的id

3).外键items_id所在的表orderdetail叫做子表;通过外键items_id指向主表(父表)items中的id

1.4 表与表之间的业务关系

在分析表与表之间的业务关系时一定要建立在某个业务意义基础上去分析。

1).先分析数据库级别之间,有关系的表之间的业务关系:

user和orders:

user  ---->orders:一个用户可以创建多个订单,一对多

orders --->user:一个订单只由一个用户创建,一对一

orders和orderdetail:

orders --->orderdetail:一个订单可以包括多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在orderdetail记录,一对多关系

orderdetail ---> orders:一个订单明细只能包括在一个订单中,一对一

orderdetail和items:

orderdetail --->items:一个订单明细只对应一个商品信息,一对一

items ---> orderdetail:一个商品可以包括在多个订单明细 ,一对多

2).再分析数据库级别之间,没有关系的表之间是否有业务关系:

orders和items:

orders和items之间可以通过orderdetail表建立关系。

1.5 画图分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NQP0J6L6-1641215111331)(image/image-20200714004659822.png)]

2.高级映射-一对一查询 2.1 需求

查询订单信息,关联查询创建订单的用户信息

2.2 sql语句
select orders.*,user.sex,user.address,user.username,user.birthday
from orders,user
where orders.user_id = user.id

2.3 使用resultMap映射的思路

使用resultMap将查询结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。

2.4 新建Orders类
import java.util.Date;


public class Orders {
    private Integer id;

    private Integer userId;

    private String number;

    private Date createtime;

    private String note;

    public Orders(Integer id, Integer userId, String number, Date createtime, String note) {
        super();
        this.id = id;
        this.userId = userId;
        this.number = number;
        this.createtime = createtime;
        this.note = note;
    }

    public Orders() {
        super();
        // TODO Auto-generated constructor stub
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }

    @Override
    public String toString() {
        return "Orders [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
                + ", note=" + note + "]";
    }

}

2.5 新建OrdersCustom类
public class OrdersCustom extends Orders{

    //resultMap方式
    //一对一 关联用户
    private UserCustom userCustom;

    public UserCustom getUserCustom() {
        return userCustom;
    }

    public void setUserCustom(UserCustom userCustom) {
        this.userCustom = userCustom;
    }

    @Override
    public String toString() {
        return super.toString()+"OrdersCustom [userCustom=" + userCustom + "]";
    }

}

2.6 创建OrdersUserMapper.xml





    
    
    
        
        
        
        
        
        

        
        
            
            
            
            
            
        
    

    
		select orders.*,user.sex,user.address,user.username,user.birthday
		from orders,user
		where orders.user_id = user.id
	




2.7 创建OrdersUserMapper.java接口
import com.cm.entity.OrdersCustom;

import java.util.List;

public interface OrdersUserMapper {

   //需求:查询订单信息,关联查询创建订单的用户信息 resultMap
   public List selectOrderUserResultMap();

}

2.8 在核心配置文件中添加扫描

  


2.9 测试类
import java.util.List;

public class OrdersUserMapperTest {

    private SqlSessionFactory factory;

    @Before
    public void setUp() throws Exception {
        factory = new SqlSessionFactoryBuilder().build(
                Resources.getResourceAsStream("sqlMapConfig.xml"));
    }

    @Test
    public void testSelectOrderUserResultMap(){
        SqlSession sqlSession = factory.openSession();
        OrdersUserMapper mapper = sqlSession.getMapper(OrdersUserMapper.class);

        List list = mapper.selectOrderUserResultMap();
        for (OrdersCustom ordersCustom : list) {
            System.out.println(ordersCustom);
        }
        sqlSession.close();
    }
}

3.高级映射-一对多查询 3.1 需求

查询订单及订单明细的信息

3.2 sql语句
select orders.*,
orderdetail.id od_id ,
orderdetail.items_id,
orderdetail.items_num
from orders,orderdetail
where orders.id = orderdetail.orders_id

3.3 新建订单详情OrderDetail类
public class OrderDetail {

	private Integer id;
	private Integer orderId;
	private Integer itemId;
	private Integer itemNum;

	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Integer getOrderId() {
		return orderId;
	}
	public void setOrderId(Integer orderId) {
		this.orderId = orderId;
	}
	public Integer getItemId() {
		return itemId;
	}
	public void setItemId(Integer itemId) {
		this.itemId = itemId;
	}
	public Integer getItemNum() {
		return itemNum;
	}
	public void setItemNum(Integer itemNum) {
		this.itemNum = itemNum;
	}
	public OrderDetail() {
		super();
		// TODO Auto-generated constructor stub
	}
	public OrderDetail(Integer id, Integer orderId, Integer itemId, Integer itemNum) {
		super();
		this.id = id;
		this.orderId = orderId;
		this.itemId = itemId;
		this.itemNum = itemNum;
	}
	@Override
	public String toString() {
		return "OrderDetail [id=" + id + ", orderId=" + orderId + ", itemId=" + itemId + ", itemNum=" + itemNum + "]";
	}

}

3.4 新建OrderDetailCustom订单详情拓展类
public class OrderDetailCustom extends OrderDetail{
}

3.5 修改OrdersCustom类
public class OrdersCustom extends Orders{

    //resultMap方式
    //一对一
    private UserCustom userCustom;
    //一对多  一个订单拥有多个订单详情
    private List detailCustomList;

    public UserCustom getUserCustom() {
        return userCustom;
    }

    public void setUserCustom(UserCustom userCustom) {
        this.userCustom = userCustom;
    }

    public List getDetailCustomList() {
        return detailCustomList;
    }

    public void setDetailCustomList(List detailCustomList) {
        this.detailCustomList = detailCustomList;
    }

     @Override
    public String toString() {
        return super.toString()+"OrdersCustom{" +
                "userCustom=" + userCustom +
                ", detailCustomList=" + detailCustomList +
                '}';
    }

}

3.6 创建OrderAndOrderDetailMapper.xml





	
	
	
		
		
		
		
		
		
		
		
			
			
			
			
		
	
	
	
	
		select orders.*,
		orderdetail.id od_id ,
		orderdetail.items_id,
		orderdetail.items_num
		from orders,orderdetail
		where orders.id = orderdetail.orders_id
	
	
	
	
	
		
		
		
		
		
			
			
			
			
			
		
	
	
	 

总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-svuW6X4t-1641215111338)(image/wps56.jpg)]

2.6 刷新缓存(清空缓存)

在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

设置statement配置中的flushCache=“true” 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

如下:



总结:一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。

2.7 二级应用场景

对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。

实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

2.8 二级缓存局限性

​ mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。

十.mybatis和spring整合 1.概念

Spring

    Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

MyBatis

   MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。MyBatis是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
2.整合思路

需要Spring通过IOC方式管理SqlSessionFactory。
spring和mybatis整合生成代理对象,使用SqlSessionFactory创建SqlSession.(Sping和mybati整合自动完成)。
持久层的mapper都交由有spring进行管理。

3.准备工作 3.1 创建一个新的Maven的java工程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O39YDZQB-1641215111338)(image/image-20210304200206857.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YQEaNcRa-1641215111339)(image/image-20210304200316460.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C9FaJyVX-1641215111339)(image/image-20210304200506823.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ypkQnQFW-1641215111340)(image/image-20210304200542827.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1oVANOZf-1641215111340)(image/image-20210304200615366.png)]

3.2 新建属性文件

创建resources文件夹,右击选择Mark Directory as 为Resources root

新建db.properties文件

#mysql
db.username = root
db.password = root
db.jdbcUrl = jdbc:mysql://localhost:3306/testmybatis?useUnicode=true&characterEncoding=utf8
db.driverClass = com.mysql.jdbc.Driver

新建log4j.properties文件

# Global logging configuration
# 在开发环境下日志级别要设置成DEBUG,生产环境设置成info或error
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

3.3 引入相关依赖

Maven引入需要的依赖


    UTF-8
    1.8
    1.8
    5.3.4



    
    
    
        org.junit.jupiter
        junit-jupiter-api
        5.7.0
    

    
    
        log4j
        log4j
        1.2.17
    

    
    
        mysql
        mysql-connector-java
        5.1.38
    
    
    
        com.mchange
        c3p0
        0.9.5.2
    

    
    
        org.mybatis
        mybatis
        3.4.6
    
    
    
        org.mybatis
        mybatis-spring
        1.3.0
    

    
    
        org.aspectj
        aspectjweaver
        1.8.13
    

    
    
        org.springframework
        spring-web
        ${spring.version}
    
    
        org.springframework
        spring-webmvc
        ${spring.version}
    
    
        org.springframework
        spring-core
        ${spring.version}
    
    
        org.springframework
        spring-oxm
        ${spring.version}
    
    
        org.springframework
        spring-tx
        ${spring.version}
    
    
        org.springframework
        spring-jdbc
        ${spring.version}
    
    
        org.springframework
        spring-aop
        ${spring.version}
    
    
        org.springframework
        spring-context-support
        ${spring.version}
    
    
        org.springframework
        spring-test
        ${spring.version}
    

    
    
        org.mybatis.generator
        mybatis-generator-core
        1.3.5
    



4.整合Spring和MyBatis XML+注解版 4.1 新建MyBatis核心配置文件

在resources文件夹下新建SqlMapConfig.xml文件





    
    
        
        
    

    
    
        
    
    


4.2 新建Spring的配置文件

在resources文件夹下,新建applicationContext.xml文件

4.2.1 配置数据源

在applicationContext.xml配置数据源、加载外部属性文件



	
    
    
	
    
    
        
        
        
        
    



4.2.2 配置SqlSessionFactory

在applicationContext.xml配置会话工厂实例


    
    
    
    


注意:

1.使用IDEA的maven工具进行开发时,会出现spring代理器无法读取mapper配置文件 XXXMaper.xml的问题—— org.apache.ibatis.binding.BindingException,可以在pom.xml中配置下面这句话:

...
    
        
        
            
                ${basedir}/src/main/java
                
                    ***.xml
                
            
            
                ${basedir}/src/main/resources
            
        
        
    

...

2.若没有添加上述配置,则需要将XxxMapper.xml文件建在resources文件夹下,并在配置SqlSessionFactory时需添加下方属性:


    
        classpath:/mapper
    //List userList = userMapper.selectListByLikeName("' or 1=1 or '");

    for (User user : userList) {
        System.out.println(user);
    }
    //4.关闭资源
    sqlSession.close();
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/695018.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号