mybatis day02
知识小结
MyBatis开发步骤:
①添加MyBatis的坐标
②创建user数据表
③编写User实体类
④编写映射文件UserMapper.xml
⑤编写核心文件SqlMapConfig.xml
⑥编写测试类
MyBatis的增删改查操作
MyBatis的插入数据操作
-
1)编写UserMapper映射文件
-
2)编写插入实体User的代码
- InputStream resourceAsStream = Resources.getResourceAsStream(“SqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
int insert = sqlSession.insert(“userMapper.add”, user);
System.out.println(insert);
//提交事务
sqlSession.commit();
sqlSession.close();
- InputStream resourceAsStream = Resources.getResourceAsStream(“SqlMapConfig.xml”);
-
3)插入操作注意问题
- 插入语句使用insert标签
- • 在映射文件中使用parameterType属性指定要插入的数据类型
- •Sql语句中使用#{实体属性名}方式引用实体中的属性值
- •插入操作使用的API是sqlSession.insert(“命名空间.id”,实体对象);
- •插入操作涉及数据库数据变化,所以要使用sqlSession对象显示的提交事务,即sqlSession.commit()
MyBatis的修改数据操作
-
1)编写UserMapper映射文件
-
2)编写修改实体User的代码
- InputStream resourceAsStream = Resources.getResourceAsStream(“SqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
int update = sqlSession.update(“userMapper.update”, user);
System.out.println(update);
sqlSession.commit();
sqlSession.close();
- InputStream resourceAsStream = Resources.getResourceAsStream(“SqlMapConfig.xml”);
-
3)修改操作注意问题
- • 修改语句使用update标签
- • 修改操作使用的API是sqlSession.update(“命名空间.id”,实体对象);
MyBatis的删除数据操作
-
1)编写UserMapper映射文件
-
2)编写删除数据的代码
- InputStream resourceAsStream = Resources.getResourceAsStream(“SqlMapConfig.xml”);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
int delete = sqlSession.delete(“userMapper.delete”,3);
System.out.println(delete);
sqlSession.commit();
sqlSession.close();
- InputStream resourceAsStream = Resources.getResourceAsStream(“SqlMapConfig.xml”);
-
3)删除操作注意问题
- • 删除语句使用delete标签
- •Sql语句中使用#{任意字符串}方式引用传递的单个参数
- •删除操作使用的API是sqlSession.delete(“命名空间.id”,Object);
MyBatis数据源DataSource
UNPOOLED 不使用连接池的数据源
POOLED 使用连接池的数据源
JNDI 使用JNDI实现的数据源
数据源DataSource的创建过程
-
- MyBatis在初始化时,解析此文件,根据的type属性来创建相应类型的的数据源DataSource,即:
- type=”POOLED” :MyBatis会创建PooledDataSource实例
- type=”UNPOOLED” :MyBatis会创建UnpooledDataSource实例
- type=”JNDI” :MyBatis会从JNDI服务上查找DataSource实例,然后返回使用
-
- 顺便说一下,MyBatis是通过工厂模式来创建数据源DataSource对象的,MyBatis定义了抽象的工厂接口:org.apache.ibatis.datasource.DataSourceFactory,通过其getDataSource()方法返回数据源DataSource
- public interface DataSourceFactory {
void setProperties(Properties props);
//生产DataSource
DataSource getDataSource();
}
mybatis事务
一.Mysql的事务级别及常见概念
MySQL事务隔离级别
事务隔离级别 脏读 不可重复读 幻读 解释
读未提交(read-uncommitted) 是 是 是 可以读到未提交的事物
不可重复读(read-committed) 否 是 是 只能读提交的事物
可重复读(repeatable-read) 否 否 是 事务提交前后都能读【MySql默认】
串行化(serializable) 否 否 否 serializable时会锁表,是最安全的,也是日常开发基本不会用
概述
-
事务是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作
-
这些操作作为一个整体一起想系统提交,要么都执行,要么都不执行
-
事务是一组不可再分割的操作集合
四大特性
-
原子性:一个事务不可分割,要么都执行,要么都不执行
-
一致性:一个事务的执行会使数据从一个一致性状态切换到另一个一致性状态
-
持久性:一个事务一旦提交,则会永久改变数据库的数据
-
隔离性:一个事务的执行不受其他事务的干扰
隔离级别
-
同时运行多个事务访问相同数据,会产生脏读,不可重复读,幻读
-
数据库系统必须具有隔离并发运行各个事务的能力,使他们不会相互影响
-
一个事务与其他事务隔离的程度成为隔离级别,级别越高,数据一致性越好,但并发性就越弱
-
平常的开发中用的不多,因为只有每次执行一个对数据库的 CRUD 才能使用
-
若是转账操作,在一个方法中需要多次交互,若每个连接处于独立的自动提交,事务是无法控制的
Mybatis 连接池
若连接池中有空闲的,直接返回适用
若没有空闲的连接,且池中的 active 连接数小于配置的最大连接数,新建一个连接返回
若无空闲连接,且池中连接数达到最大,不创建新连接,从 activeConnection 表中返回一个最老的值
看这个连接被取出来的时间是否超出 20 秒,若超过,使这个连接失败,且使这个连接返回做下一个操作
Mybatis 注解开发
步骤
-
在核心配置文件映射 RoleDao 接口文件
-
在接口方法上加入注解 @Insert、@Update、@Delete、@Select
建立实体类属性和数据表中列的对应关系
-
1.使用注解实现复杂关系映射开发
-
在XML文件中有resultMap元素,注解有、@Results @Result @One @Many注解
-
-
2.使用@Results和@Result注解解决属性和列名不一致问题
使用二级缓存
-
@CacheNamespcae(blocking = true)
-
public interface UserMapper{}
Mybatis 工具类
在用MyBatis框架连接数据库时,往往要经常创建sessionFactory,重复的编写大量代码,故将其中的重复代码提出成一个工具类,这样直接调用方法即可,可简化代码编写和优化运行效率,不需要重复的读取mybatis核心配置文件和反复new工厂对象
- 其中的Mybatis_config.xml是我的MyBatis的核心配置文件。
- 用静态代码块进行创建SqlSessionFactory,只在类加载时创建一次,保证了整个程序运行时只有一个工厂实例。
- 用线程变量保存session对象,是为了线程安全着想,这样自己的线程管理自己线程的session,不会出现多实例同时调用同一个session对象,造成数据不准确的情况出现。
- MyBatisUtil.getSession(); 即可获得session对象;
- MyBatisUtil.closeSession(); 即可关闭线程对象,务必要在session使用完毕后关闭session。
private static SqlSessionFactory sessionFactory = null;
/*
* 创建本地线程变量,为每一个线程独立管理一个session对象 每一个线程只有且仅有单独且唯一的一个session对象
* 加上线程变量对session进行管理,可以保证线程安全,避免多实例同时调用同一个session对象
* 每一个线程都会new一个线程变量,从而分配到自己的session对象
*/
private static ThreadLocal<SqlSession> threadlocal = new ThreadLocal<SqlSession>();
// 创建sessionFactory对象,因为整个应用程序只需要一个实例对象,故用静态代码块
static {
try {
Reader reader = Resources.getResourceAsReader("Mybatis_config.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 返回sessionFactory对象 工厂对象
*
* @return sessionFactory
*/
public static SqlSessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* 新建session会话,并把session放在线程变量中
*/
private static void newSession() {
// 打开一个session会话
SqlSession session = sessionFactory.openSession();
// 将session会话保存在本线程变量中
threadlocal.set(session);
}
/**
* 返回session对象
* @return session
*/
public static SqlSession getSession(){
//优先从线程变量中取session对象
SqlSession session = threadlocal.get();
//如果线程变量中的session为null,
if(session==null){
//新建session会话,并把session放在线程变量中
newSession();
//再次从线程变量中取session对象
session = threadlocal.get();
}
return session;
}
/**
* 关闭session对象,并从线程变量中删除
*/
public static void closeSession(){
//读取出线程变量中session对象
SqlSession session = threadlocal.get();
//如果session对象不为空,关闭sessoin对象,并清空线程变量
if(session!=null){
session.close();
threadlocal.set(null);
}
}
}