Mybatis

Mybatis

他是一个支持普通Sql查询,存储过程和高级映射的一个优秀的持久层框架,他是一个用来操作数据库的一个框架

环境搭建:

  1. 导入两个jar包 一个是mybatis的核心jar,一个是mysql的数据库连接驱动
  2. 书写主配置文件(mybatis.xml):在主配置文件中配置数据库的连接信息(数据库驱动、url、usenrame、password等)
  3. 书写局部配置文件(xxx.xml):局部配置文件的名字与dao层的类名保持一致,局部配置文件用来保存sql语句
  4. 将主配置文件(mybatis.xml)与局部配置文件(xxx.xml)关联起来
  5. 写一个实体类,实体类里面的属性及数据类型要与数据库中相同
  6. 写一个实现类跟局部配置文件在同一个包下

xml中的注释快捷键:

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>
    <!-- 別名的配置必须放到配置标签中的第一行,不然会报错(配置的是局部配置中返回类型的别名) -->
	<typeAliases>
		<!-- type:表示的是某一个实体类的具体路径,alias代表具体路径的别名 -->
		<typeAlias type="com.mao.model.Man" alias="Man"/>
	</typeAliases>
	<!-- 注释快捷键 ctrl+shift+/ -->
    <!-- 这里的default的值必须与下面的id保持一致 -->
	<environments default="mysql">
        <!-- environments 代表环境,环境就包括了事务跟数据源 -->
		<environment id="mysql">
		<!--  
			transactionManager:代表的是数据库的事务
			他的type属性统一使用JDBC
		-->
			<transactionManager type="JDBC"></transactionManager>
			<!-- 
				dataSource:代表数据源
				数据源中需要配置我们的 MySQL驱动,url,username,password
				type也是固定值 : POOLED
			 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/iot"/>
				<property name="username" value="root"/>
				<property name="password" value="258025"/>
			</dataSource>
		</environment>
	</environments>
    <mappers>
		<mapper resource="com/mao/dao/impl/StudentDaoImpl.xml"/>
	</mappers>
</configuration>

局部配置

<?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是局部配置文件中的根标签,类似于html文件中的html标签
	namespace:代表的是唯一的表示符,其值与某一个dao层类的路径保持一致
 -->
<mapper namespace="com.mao.dao.impl.StudentDaoImpl">
    <!-- sql标签,用来存放公共字段的,可以配合<include/>标签在其他sql语句中引用 -->
    <sql id="commont">
		id,name,age,birth
	</sql>
	<!-- 
		在Mybatis中查询语句必须放在select标签中;添加语句必须放在Insert标签中;
		修改、删除等都必须放在各自对应的标签
	 -->
	 <!-- 
		  这里的id要与我们引用的dao类中的方法名保持一致
	 	  resultType就是指定我们查询后返回的一个类型,若是查询多条也可以
		  parameterType是用于条件查询时,我们接受的数据类型
	  -->
	 <select id="selectAll"	resultType="com.mao.model.Student">
	 	select <include refid="commont"/> from student;
	 </select>
    <select id="selectAll2"	resultType="Map">
	 	select * from student;
	 </select>
    <select id="selectDynamic" parameterType="Map" resultType="Map">
	 	select <include refid="commont"/> from man 
        <!-- 这里运用了trim标签 -->
		<trim prefix="where" suffixOverrides="and|or">
	 		<if test="id!=null">
	 			id=1 and
	 		</if>
	 		<if test="name!=null">
	 			name=#{name} or
		 	</if>
	 		<if test="age!=null">
	 			age=#{age}
	 		</if>
	 	</trim>
	 	<!-- 可以写无限个判断来进行条件查询,在if标签内取值不需要使用#{}可以直接使用字段进行判断 -->
	 </select>
    
    <!-- 这里的resultType的值Man是com.mao.model.Man的别名,我们在主配置文件中配置好了的 -->
	 <select id="selectById" parameterType="int" resultType="Man">
	 	select * from Man where id=#{0};
	 </select>
	 <select id="selectByTj" parameterType="Map" resultType="com.mao.model.Man">
         <!-- 注意,这里的name后面的传值不用加上引号 不然会报错 -->
	 	select * from Man where name=#{name} and age=#{age};
	 </select>
	 <!-- 这里的参数跟返回类型互换了一下 -->
	 <select id="selectByTj2" parameterType="com.mao.model.Man" resultType="Map">
	 	select * from Man where name=#{name} and age=#{age};
	 </select>
    
     <!-- insert、update、delete都不需要设置返回值 ,因为他返回的是int类型,影响的行数 -->
	 <insert id="addMan" parameterType="Map">
	 	insert into man set id=#{id},name=#{name},age=#{age},birth=#{birth};
	 </insert>
	 <update id="updateMan" parameterType="Map">
	 	update man set name=#{name},age=#{age} where id = #{id};
	 </update>
	 <delete id="deleteMan" parameterType="int">
	 	delete from man where id = #{0};
	 </delete>
</mapper>

实现类模板

		//1、需要执行sql语句(SqlSession---->SqlSessionFactory----->SqlSessionFactoryBuilder)
		SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
		//将mybatis.xml主配置文件变成字节输入流
		InputStream ins = Resources.getResourceAsStream( "mybatis.xml");
		SqlSessionFactory ssf = sfb.build(ins);
		SqlSession session= ssf.openSession();
		List<Student> lists = 					      	  	 	 	 	 		   session.selectList("com.mao.dao.impl.StudentDaoImpl.selectAll");
		for (Student student : lists) {
			System.out.println(student);
		}

可以将获得Session放到一个init()方法中,每次执行只需要调用一次init()

	private static SqlSession session = null;
	public void init(){
		//1、需要执行sql语句(SqlSession---->SqlSessionFactory----->SqlSessionFactoryBuilder)
		//将mybatis.xml主配置文件变成字节输入流
		try {
			SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
			InputStream ins = Resources.getResourceAsStream("mybatis.xml");
			SqlSessionFactory ssf = sfb.build(ins);
			session= ssf.openSession();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

实现类是如何使用查询的

//前面定义了一个公共的一个session
	public void selectAll(){
        //可以用对象来接收
		List<Man> lists = session.selectList("com.mao.dao.impl.ManDaoImpl.selectAll");
		for (Man man : lists) {
			System.out.println(man);
		}
	}
public void selectAll2(){
    	//也可以用Map接收
		List<Map<String,Object>> lists = session.selectList("com.mao.dao.impl.ManDaoImpl.selectAll2");
		for (Map<String,Object> man : lists) {
			System.out.println(man);
		}
	}
	
	public void selectById(){
		Man man = session.selectOne("com.mao.dao.impl.ManDaoImpl.selectById",1);
		System.out.println(man);
	}
	
	public void selectByTj(){
		HashMap<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("name", "毛毛");
		parameters.put("age", 20);
		List<Man> man = session.selectList("com.mao.dao.impl.ManDaoImpl.selectByTj",parameters);
		System.out.println(man);
	}
	
	public void selectByTj2(){
		Man man = new Man();
		man.setName("傻猫"); 
		man.setAge(2);
		List<Map<String, Object>> map = session.selectList("com.mao.dao.impl.ManDaoImpl.selectByTj2",man);
		for (Map<String, Object> map2 : map) {
			System.out.println(map2);
		}
	}

	public void addMan(){
		HashMap<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("id", 3);
		parameters.put("name", "傻狗");
		parameters.put("age", 5);
		parameters.put("birth", "2022-03-07 00:00:00");
		int s = session.insert("com.mao.dao.impl.ManDaoImpl.addMan", parameters);
		if(s>0){
			System.out.println("数据添加成功!");
			session.commit();
		}else{
			System.out.println("数据添加失败,请重新添加!");
		}
	}
	
	public void updateMan(){
		HashMap<String,Object> map = new HashMap<String,Object>();
		map.put("name", "傻猫");
		map.put("age", 2);
		map.put("id", 3);
		int s = session.update("com.mao.dao.impl.ManDaoImpl.updateMan", map);
		if(s>0){
			System.out.println("数据修改成功!");
			session.commit();
		}else{
			System.out.println("数据修改失败,请重新添加!");
		}
	}
	
	public void deleteMan(){
		int s = session.delete("com.mao.dao.impl.ManDaoImpl.deleteMan",1);
		if(s>0){
			System.out.println("数据删除成功!");
			session.commit();
		}else{
			System.out.println("数据删除失败,请重新删除!");
		}
	}
	//动态sql
	public void selectDynamic(){
		HashMap<String, Object> map = new HashMap<String,Object>();
		map.put("id", 1);
		map.put("name", "毛毛");
		List<Map<String, Object>> mapList = session.selectList("com.mao.dao.impl.ManDaoImpl.selectDynamic",map);
		for (Map<String, Object> map2 : mapList) {
			System.out.println(map2);
		}
	}

增删改查 注意事项!!!需要注意

  1. 查询数据:在Mybatis.框架中,查询对应的sql语句需要书写在select标签中。

    1. 查询时必须指定返回的数据类型
    2. 如果是带条件的查询语句,则需通过select标签中的parameterType指定条件的类型
  2. 增删改:在Mybatis.框架中,添加对应的sql语句需要书写在insert、delete、update标签中

    1. 添加千万不要指定返回的数据类型(增、删、改这三个操作返回类型默认均为in类型,代表影响的行数)
    2. 添加和修改时的参数信息类型需要指定parameterType
    3. 在企业的实际开发中大多数情况是通过id(主键)来删除数据的
    4. 增删改数据时需要提交事务(删除、修改也需要提交事务,查询不需要) SqlSession.commit();
  3. 回滚就是SqlSession.rollback(); 使用完记得将其关闭,SqlSession.close();

其他标签:

别名标签(typeAliases):
typeAliases,标签是写实体类的别名,写了之后可以在写Sql配置文件时,例如:
select标签中的属性就可以不用写实体类的具体路径直接用别名就可以了
typeAliases.的别名配置需要书写在主配置文件中的中的第一行(mybaits.xml), 否则会报错

sql:
在mybatis.中有一个标签叫做sql,但这个标签不是用来书写sql语句的,而是用来存放公共的字段。在局部配置文件中的mapper标签中定义,推荐写到第一行

nclude:
在mybatis,框架中include标签代表引用的含义,它和sql标签是一对组合标签。include标签可以将sql_标签中的公共代码引用到其它的标签之中。

where:
当where标签中有内容时,会自动生成where关键字,并且将内容前多余的and或or去掉
当where标签中没有内容时,此时where标签没有任何效果

trim :
若标签中有内容时:
prefix |suffix:将trim标签中内容前面或后面添加指定内容
suffixoverrides |prefixoverrides :将trim标签中内容前面或后面去掉指定内容
若标签中没有内容时,trim标签也没有任何效果

choose、when、otherwise
when和otherwise写在choose标签里面。相当if...else if...elsewhen至少要有一个,otherwise最多只能有一个

foreach:

<foreach collection="eids" item="eid" separator="," open="(" close=")">
    {eid}
</foreach>
<!-- collection="遍历的数组" item="数组中的每个元素" separator="每个元素之间的分隔符"
 open="以什么开始" close="以什么结束"	若出现数组无法获取的时候,可以在调用方法时使用@param(参数)注解,他会让程序自动识别可以被使用的数据类型 -->

特殊符号:

  1. ">":在mybatis.框架中使用"&gt+;"代替(g代表的是单词greater,t代表的是单词than) 注意分号不要漏写
  2. "<":在mybatis.框架中使用”&lt+;"代替(I代表的是单词less,t代表的是单词than) 注意分号不要漏写
  3. "=":等于符号可以直接书写

$与#取数据区别: 推荐使用#,尽量不使用$

$、#都可以用来取集合中的参数,但是使用$符号取数据时不能够防止sql注入。因此在实际的项目开发中,尽量使用#来获取集合中的参数信息。(面试题)

  1. 将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如: order by #user_id#,

    如果传入的值是111,那么解析成sql时的值为order by "111",如果传入的值是id,则解析成的sql为order by "id".

    但是在sql语句中,数字类型的值加不加双引号都可以

  2. $将传入的数据直接显示生成在sal中。如: order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by 111,如果传入的值是id,则解析成的sql为order by id.(面试题)

  3. 也就是#会自动加双引号,$不会自动加双引号,会直接显示

MyBatis的缓存

(注意:缓存只对我们的查询有效)

  1. MyBatis的一级缓存

    —级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问

    使─级缓存失效的四种情况:

    1. 不同的SqlSession对应不同的—级缓存
    2. 同一个SqlSession但是查询条件不同
    3. 同一个SqlSession两次查询期间执行了任何一次增删改操作
    4. 同一个SqlISession两次查询期间手动清空了缓存
  2. MyBatis的二级缓存

    二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

    二级缓存开启的条件:

    1. 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
    2. 在映射文件中设置标签
    3. 二级缓存必须在SqlSession关闭或提交之后有效

【狂神说Java】MyBatisPlus学习笔记-KuangStudy-文章

逆向工程?

俗称代码生成器

  • 正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。

  • 逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:

    • o Java实体类

    • o Mapper接口

    • o Mapper映射文件

一些报错以及处理方式

当报错Could not find result map 原因是局部配置的resultType写成了resultMapimage-20220308135748520

image-20220308135715314

当打开Session报错SqlSession session= ssf.openSession();

image-20220308135852765

原因是image-20220308140033429default的值跟id保持一致

mybatis参数为map的坑 自动增加""引号问题 可参考

(44条消息) mybatis参数为map的坑 自动增加‘‘‘‘引号问题_@畅的博客-CSDN博客

posted @   没有烦恼的猫猫  阅读(196)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示