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

Mybatis 学习笔记(仅记录自己学习过程)

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

Mybatis 学习笔记(仅记录自己学习过程)

本内容为本人在哔站学习由notepad++实时记录,没有经过idea编译,直接又贴入本博客以防止丢失,如有错误之处,还望指正,谢谢大家

建立数据库

create database 'mybatis'
use 'mybatis';
create table 'user'(
	'id' int(20) not null primary key,
	'name' varchar(30) default null,
	'pwd' varchar(30) default null
)engine = innodb default charset= utf-8;

insert into 'user'('id','name','pwd') values
(1,'狂神','123456'),
(2,'狂神','123456'),
(3,'狂神','123456');

//mybatis-config.xml mabatis核心配置文件,写在resources文件下面


	
	
		
		
			
			
			
			
			
		
	


注意::::::::::::::每一个Mapper.xml都需要在mabatis核心配置文件中注册

	



//工具类 sqlSessionFactory -->sqlSession

public class MybatisUtils{
	private static SqlSessionFactory sqlSessionFactory;
	static{
		String resource="mybatis-config.xml"
		InputStream inputStream = Resources.getResourceAsStream(resource);
		sqlSessionFactory = new  SqlSessionFactoryBuilder().build(inputStream)
	}
	//有了SqlSesion,可以从汇总获得SqlSession的实例
	//SqlSession完全包含了面向数据库执行Sql命令所需要的所有方法
	public static SqlSession getSqlSession(){
		return sqlSessionFactory.openSession();	
	}
		
}

//实体类

public class User{
	private int id;
	private String name;
	private String pwd;
	
	public User(){}
	public User(){
		this.id = id;
		this.name = name;
		this.pwd = pwd;
	}
	
	
	get   set方法  toString
}

//dao

public  interface UserDao{
	//扩展:模糊查询
	List getUserLike(String value);
	//查询全部用户
	List getUserList();
	//根据id查询用户
	User getUserById(int id);
	//insert一个用户
	int addUser(User user);
	//通过map方式
	int addUser(Map map)
	//修改用户
	int updateUser(User user);
	//删除一个用户
	boolean deleteUser(int id);	
}
public class UserDaoImpl implements UserDao{
	public List getUserList(){
		//执行sql
		String sql = "select * from mybatis.user"
		//结果集 
		resultSet
	   	return null;
	}
}

//接口实现类由原来的UserDaoImpl转变为一个Mapper配置文件

//UserMapper.xml



//namespace=绑定一个对应的Dao/Mapper接口


	
		select * from  mybatis.user where  name like "%"#{value}"%"
	
	
	//select查询语句 id相当于 原来impl实现类中的方法名	
	
		select * from mybatis.user where id = #{id}
	
	
	//insert一个用户
	
		insert into  mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd});
	
		
	//万能map   不需要传递所有参数,,可以只传递部分参数,不需要像对象那要传递那么多参数
	
		insert into imybatis.user (id,pwd) values (#{userid},#{password})
	
	
	//修改用户
	
		update mybatis.user set name= #{name},pwd=#{pwd} where id =#{id};
	
	
	//删除一个用户
	
		delete from mybatis.user where id = #{id};
	
	

public class UserDaoTest{
	@Test
	public void getUserLike(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		
		List userlist = mapper.getUserLike("%李%");
		for(User user:userList){
			
		}
		
		sqlSession.commit();
		sqlSession.close();
	}

	@Test 
	public void test(){
		//第一步:获得SqlSession对象
		SqlSesson sqlSession = MybatisUtils.getSqlSession();
		
		
		//方式一:getMapper   推荐
		UserDao userDao = sqlSession.getMapper(UserDao.class);
		List userList = userDao.getUserList();
		
		//方式二:
		List userList = sqlSession.selectList("com.kuang.dao.UserDao.getUserList");
		
		for(User user :userList){
			System.out.println(userList);
		}
		sqlSession.close();		
	}
	
	@Test
	public void getUserById(){
		SqlSesson sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		User user = mapper.getUserById(1);
		System.out.println(user);
		
		sqlSession.close();
	}
	//增删改需要提交事务
	@Test 
	public void addUser(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper  = sqlSession.getMapper(UserMapper.class) //视频中将UserDao.class改名为UserMapper
	
		
		int res = mapper.addUser(new User(4,"呵呵","123132"));
		//提交事务(必须,,,,否则数据库不会改变)
		sqlSession.commit();
		
		sqlSession.close();
	}
	
	@Test
	public void updateUser(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		int num = mapper.upadateUser(new User(4,"七七","15646"));
		sqlSession.commit();
		sqlSession.close();
	}
	@Test
	public void deleteUser(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = SqlSession.getMapper(UserMapper.class);
		boolean result = mapper.deleteUser(4);
		sqlSession.commit();
		sqlSession.close();
		
	}
	
	//万能的map,用了 map就不需要传所有的参数
	@Test
	public void addUser2(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession(UserMapper.class);
		Map map = new HashMap();
		map.put ("userid",5);
		map.put("password","33333");
		mapper.addUser2(map);
		sqlSession.close();
	}
	
}

//name中的包名要和Dao/mapper接口包名一直

select
选择查询语句
id:就是对应的namespace中的方法名;
resultType:Sql语句执行的返回值
parameterType:参数类型

万能的map
假设,我们的实体类 或者数据库中的表,,字段或者参数过多,我们应当考虑使用Map

map传递参数,直接在sql中取出key即可 parameterType=“map”
想传什么传什么即可,相当于可定制化,,

对象传递参数,直接在sql中取对象的属性即可 parameterType=“Object”

只有 一个 基本参数的类型的情况下,直接在sql中去掉,
boolean deleteUser(int id);

多个参数用Map,或者注解。
boolean deleteUser(int id ,ArgType arg);

在xml中所有的标签都可以定义顺序

配置解析

在核心配置文件中引入外部配置文件


	
	

可以直接引入外部文件
可以在其中增加一些属性配置
如果两个文件有同一个字段,优先使用外部配置文件的

核心配置文件
mybatis-02
------------db.properties(在config中再引入,,直接写参数名)

driver = com.mysql.jdbc.Driver
url= jdbc:mysql:localhost:3306:mybatis?
username = root
password=root

类型别名(注意在配置文件中的位置) resultType=“com.kuang.pojo.User”
类型别名是为java类型设置一个短的名字
存在的意义仅在于用来减少完全限定名的冗余

可以给实体类其别名



也可以指定一个包名,MyBatis会子啊包名下搜索需要的java Bean
扫描实体类的包,他的默认别名就为实体类的 类名,首字母小写


在实体类比较少的时候使用第一种
在实体类十分多的时候建议使用第二种
第一种可以自定义别名,,第二种不行,如果非要改 需要在实体类上加注解

lastName 数据库中用last_name是因为oracal中全部转换为大写的 增加可读性

其他配置
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins插件
mybatis_generator=core
mybatis-plus
通用mapper

映射器(mappers)
MapperRegistry:注册绑定我们的Mapper文件

方式一:

	
方式二:使用class文件绑定注册

	

注意点:
接口和他的Mapper配置文件必须同名
接口和他的Mapper配置文件必须在同一文件下
方式三:使用扫描包进行注入绑定



注意点:
接口和他的Mapper配置文件必须同名
接口和他的Mapper配置文件必须在同一文件下

生命周期和作用域
生命周期 和作用域 是至关重要的 因为错误的使用回导致非常严重的并发问题
SqlSessionFactoryBuilder:
一旦船舰了SqlSessionFactory,就不需要它了
局部变量
SqlSessionFactory
说白了就是数据库连接池 (创建后一直存在 等待其他其他人来连接, 最后回收)
SqlSessionFactory一旦被穿甲就应该在应用运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
因此SqlSessionFactory的最佳作用域是应用作用域

最简单的就是使用当立模式或者静态单例模式。

SqlSession
连接到连接池的一个请求
SqlSession的实例并不是线程安全的,因此是不能被共吸纳的,,所哟一他的最佳的作用域是请求或方法作用域
用完之后赶紧关闭,否则资源被占用

SqlSessionFacotryBuilder 造车工厂 造了100台车.然后卖给了租车公司 (SqlSessionFactory).然后直接倒闭.

解决属性名和字段名不一致的问题
select * from mybatis.user where id = #{id}
select id,name,pwd from mybatis.user where id = #{id}
解决方法:

	方法一:起别名  
	
		select id,name ,pwd  as password from mybatis.user where id = #{id}
	
			
	方法二:结果映射集resultMap

	  column 数据库中的字段,property实体类中的属性
	
	


		
		select * from student
	
	
	
		
		
		//复杂的属性,需要单独处理,对象association,,集合:collection
				
	
	
	
		select s.id sid,s.name sname,t.name tname
		from studnet s,teacher t
		where s.tid= t.id;		
	
	
	
		
		
		
			
		
	

TeacherMapper.xml




mybatis.config.xml中加入

	

public class MyTest{
	public static void main(String [] args){
		SqlSession	sqlSession = MybatisUtils.getSqlSession();
		TeacherMapper mapper =sqlSession.getMapper(TeacherMapper.class);		
		Teacher teacher = mapper.getTeacher(1);
		System.out.println(teacher);
		SqlSession.close();
	}
	
	@Test
	public void testStudent(){
		SqlSession	sqlSession = MybatisUtils.getSqlSession();		
		StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
		List student= mapper.getStudent();
		for(Student student:studentList){
			System.out.println(student);
		}
		
		SqlSession.close();
	}
	
}

测试环境搭建
导入lombok
新建实体类Teacher,Student
新建Mapper接口
建立Mapper.XML文件
在核心配置文件中绑定注册我梦的Mapper接口文件
测试查询是否能够成功

一对多处理
比如一个老师拥有多个学生
对于老师而言,就是一对多

@Data
public class Studnet{
	private int id ;
	private String name;
	private int tid;
}

@Data
public class Teacher{
	private int id;
	private String name;
	//一个老师拥有多个学生
	private List students;
}
public interface TeacherMapper{
	//获取老师
	List getTeacher();
	//获取指定老师下的所有学生及老师的信息
	Teacher getTeacher(@Param(tid) int id);
	
	Teacher getTeacher2(@Param(tid) int id);
	
}

select s.id sid,s.name sname,t.name tname,t.id tid
from student s,teacher t
where s.tid = t.id
====================按结果嵌套查询


	
		select s.id sid,s.name sname,t.name tname,t.id tid
		from student s,teacher t
		where s.tid = t.id and t.id = #{tid}
	
	
	
		
		
		//复杂的属性,我们需要单独处理  对象association 集合:collection
		//javaType="指定属性的类型" ,,集合中的泛型信息,我们使用ofType获取
		
			
			
			
		
	

====================按查询嵌套处理


		select * from mybatis.student where tid=#{tid} 
	

public classs MyTest{
	@Test
	public void test(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
		List teacher = mapper.getTeacher();
		for(Teacher teacher:teachers){
			System.out.println(teacher);
		}
		sqlSession.close();
	}
	@Test
	public void test(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
		Teacher teacher = mapper.getTeacher(1);
		System.out.println(teacher);
		
		sqlSession.close();
	}
}

小结:
关联: association 多对一----------------
集合: collection 一对多
javaType & ofType
javaType是用来指定实体类中属性的类型
ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型;
注意: 保证sql的可读性,尽量保证通俗易懂
注意一对多和多对一中,属性名和字段的问题
如果问题不好排查,可以使用日志,建议log4j

面试高频
mysql引擎:InnoDB底层原理 索引,索引优化

动态sql
什么是动态Sql: 动态sql就是根据不同的条件生成不同的sql语句
创建一个工程:
导包
编写配置文件
编写实体类
编写实体类对应的Mapper接口和Mapper.xml文件

@Data	
public class Blog{
	private int id;
	private String author;
	private Date createTime;//属性名和字段名不一致
	private int views;
}
-----------------BlogMapper.java-----------
public interface BlogMapper{
	//插入数据
	int addBlog(Bolg bolg);
	//查询博客
	List queryBlogIF(Map map);
	List queryBlogChoose(Map map);
	//更新博客
	int updateBlog(Map map);
	//查询地1-2-3号记录的访客
	List queryBlogForeach(Map map);
	
	
	
}

----------------BlogMapper.xml----------


	
		insert into mybatis.blog(id,title,author,create_time,views)
		values (#{id},#{title},#{author},#{create_time},#{views})
	
	//通过if动态查询
	
			
				
					title=#{title}
				
				
					and author=#{author}
				
				
					and views=#{views}
				
			
		
	
	
	
		update mybatis.blog
		
			
				title = #{title},
			
			
				author = #{author}
			
		
		where id =#{id}
	

	//我们现在传递一个万能的map,这个map中可以存在一个集合 
	//select * from mybatis.blog where 1=1 and (id=1 or id=2 or id=3)  语句智能去掉where 1==1
	
		select * from mybatis.blog
		
			
				id=#{id}
			
		
	
	


public class MyTest{
	@Test
	public void addBlogTest(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    Blog blog = new Blog();
    blog.setId(IDutils.getId());
    blog.setTitle(Mybatis);
    blog.setAuthor(狂神说);
    blog.setCreateTime(new Date());
    blog.setViews(9999);

    mapper.addBook(blog);

    blog.setId(IDutils.getId());
    blog.setTitle(Java);
    mapper.addBook(blog);

    blog.setId(IDutils.getId());
    blog.setTitle(Spring);
    mapper.addBook(blog);

    blog.setId(IDutils.getId());
    blog.setTitle(微服务);
    mapper.addBook(blog);

    sqlSession.close();
}

	@Test
	public void queryBlogIF(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
		
		HashMap	map = new HashMap();
		map.put("title","java如此简单");
		map.put("author","狂神说")
		
		Lish blogs = mapper.queryBlogIF(map);
		for(Blog blog :blogs){
			System.out.println(blog);
		}		
		sqlSession.close();
	}
	@Test
	public void queryBlogForEach(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
		HashMap map = new HashMap();
		ArrayList ids = new ArrayList();
		//ids.add(1);
		//ids.add()2;

		map.put("ids",ids);
		List blogs = mapper.queryBlogForeach(map);
		for(Blog blogs:blog){
			System.out.println(blog);
		}
		sqlSession.close();
	}
	
@SuppressWarnings("all")//抑制警告
public class IDutils{
	public static Stirng getId(){
		return UUID.randomUUID().toString().replaceAll("-",".");		
	}
	@Test
	public void test(){
		System.out.println(IDutils.getId());
	}

}	

所谓的动态sql本质还是sql语句,只是我们可以在sql层面,去执行一个逻辑代码

sql片段:
有的时候,我们可能将一些功能的部分抽取出来,方便复用,
重复代码复用时,可以使用这种代码片段;

1.使用sql标签抽取公共的部分,

	
		title = #{title},
	
	
		author = #{author}
	

2.在需要使用的地方使用include标签引用即可

		update mybatis.blog
		
			
		
		where id =#{id}

片段中注意事项:
最好基于单表来定义sql片段
不要存在where标签

动态sql就是在拼接sql语句,我们只要保证sql的准确性,按照sql的格式,去排列组合就可以了
先在Mysql中写出完整的sql,再对应的去修改成为我们的动态sql实现通用即可。

缓存
查询:连接数据库,耗资源
一次查询的结果,给他暂存在一个可以直接取到的地方;;内存:缓存
我们再次查询相同数据的时候,直接走缓存,就可以了

测试步骤
开启日志,测试在一个Session中查询两次相同的记录,查看日志输出

	public interface UserMapper{
			//根据id查询用户
			User queryUserById(@Param("id") int id);  
	}

//在配置中开启别名后  resultType不需要全类名
	

public class Mytest{
	@Test
	Public void test(){
	SqlSession sqlSession = MybatisUtils.getSqlSession();
	UserMapper mapper = sqlSession.getMapper(UserMapper.class);
	User user = mapper.queryUser(1);
	System.out.println(user);
	
	User user2 = mapper.queryUser(1);
	System.out.println(user2);
	//user 和user2用的缓存,相当于只做了最后的查询
	sqlSession.close();
	}
}

缓存失效的情况:
查询不同的东西
增删改操作,可能会改变原来的数据,所以必定会刷新缓存。。。
查询不同的Mapper.xml
手动清理缓存 sqlSession.clearCache();

小结:一级缓存默认是开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个区间(用缓存,而不是频繁操作数据库)

二级缓存:二级缓存也叫全局缓存,一级缓存的作用域太低了,所以诞生了二级缓存
一个会话查询一个数据,这个数据就会被放在当前会话的一级缓存中
如果当前的会话关闭了,这个会话对应的一级缓存就没有了,但是我们想要的是,会话关闭了,一级缓存中的数据会被保存到二级缓存中。
新的会话查询信息,就可以从二级缓存中获取内容
不同的mapper查出的数据会放在自己对应的缓存(map)中。

开启全局缓存 

小结:只要开启了二级缓存,在同一个Mapper下有效
所有的数据都会先放在一级缓存中
只有当会话提交,或者关闭的时候 ,才会提交到二级缓存中。


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

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

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