MyBatis学习总结一(SSM框架)

MyBatis学习总结二
MyBatis封装类

一. 三层架构

界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
数据访问层: 就是访问数据库, 执行对数据的查询,修改,删除等等的。

三层对应的包

界面层: controller包 (servlet)
业务逻辑层: service 包(XXXService类)
数据访问层: dao包(XXXDao类)

三层中类的交互

用户使用界面层–> 业务逻辑层—>数据访问层(持久层)–>数据库(mysql)

三层对应的处理框架

界面层—servlet—springmvc(框架)
业务逻辑层—service类–spring(框架)
数据访问层—dao类–mybatis(框架)

二.框架

模版:
1. 规定了好一些条款,内容。
2. 加入自己的东西

框架特点:
1. 框架一般不是全能的, 不能做所有事情
2. 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
3. 框架是一个软件

三.mybatis框架

介绍: 一个框架,早期叫做ibatis, 代码在github。
mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
(1)sql mapper :sql映射
可以把数据库表中的一行数据 映射为 一个java对象。
一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据

(2) Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。

mybatis提供了哪些功能:

  1. 提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了
  2. 提供了执行sql语句的能力, 不用你执行sql
  3. 提供了循环sql, 把sql的结果转为java对象, List集合的能力
    while (rs.next()) {
    Student stu = new Student();
    stu.setId(rs.getInt(“id”));
    stu.setName(rs.getString(“name”));
    stu.setAge(rs.getInt(“age”));
    //从数据库取出数据转为 Student 对象,封装到 List 集合
    stuList.add(stu);
    }
    4.提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet

开发人员做的是: 提供sql语句
最后是: 开发人员提供sql语句–mybatis处理sql—开发人员得到List集合或java对象(表中的数据)

总结:
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行。

3.1 开发mybatis程序从步骤:

1.配置mybatis

(1)conf.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>
<!--通过environments的default值和environment的id来制定MyBatis运行时的数据库环境-->
	<environments default="development">
		<!--开发环境(自己的计算机)-->
		<environment id="development">
		<!--事务提交方式:
			JDBC:利用JDBC方式处理事务(commit rollback close)
			MANAGED:将事务提交由其他组件去托管(spring,jobss),默认会关闭连接。
		-->
		<transactionManager type="JDBC"/>
			<!--数据源类型:
				UNPOOLED:传统JDBC模式(每次访问数据库,均需要打开,关闭等数据库)
				POOLED:使用数据库连接池
				JNDI:从tomcat中获取一个内置的数据库连接池(数据库连接池-数据)
			-->
			<dataSource type="POOLED">
			<!-- 配置数据库信息 -->
			<property name="driver" value="oracle.jdbc.OracleDriver"/>
			<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:ORCL"/>
			<property name="username" value="scott"/>
			<property name="password" value="tiger"/>
		</dataSource>
		</environment>
	</environments>
	<mappers>
		<!-- 加载映射文件 -->
		<mapper resource="org/lanqiao/entity/personMapper.xml"/>
	</mappers>
</configuration>

注意事项:
如果使用的 事务方式为 jdbc,则需要 手工commit提交,即session.commit();

(2)映射文件personMapper.xml :增删改查标签

<?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 namespace="org.lanqiao.entity.personMapper">

	<!--mybatis约定:输入参数parameterType 和 输出参数resultType ,在形式上都只能有一个-->
	<select id="queryPersonById" resultType="org.lanqiao.entity.Person"  parameterType="int">
		select * from person where  id = #{id} 
	</select>		
</mapper>

输出参数: 如果返回值类型是一个 对象(如Student),则无论返回一个、还是多个,
resultType都写成org.lanqiao.entity.Student

(3)测试类:
session.selectOne(“需要查询的SQL的namespace.id”,“SQL的参数值”);

public class TestMyBatis {
	public static void main(String[] args) throws IOException {
		//加载MyBatis配置文件(为了访问数据库)
		Reader reader = Resources.getResourceAsReader("conf.xml") ;
		SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader) ;
		//session - connection
			
		SqlSession session = sessionFactory.openSession() ;
		String statement = "org.lanqiao.entity.personMapper.queryPersonById" ;
		Student person = session.selectOne( statement,1 ) ;
		System.out.println(person);
		session.close(); 	
	}

3.2 mapper动态代理方式的CRUD(MyBatis接口开发):

原则:约定优于配置
硬编码方式

abc.java
Configuration conf = new Configuration();
con.setName(“myProject”) ;

配置方式:

abc.xml
myProject

约定:默认值就是myProject

1.具体实现的步骤:

1.基础环境:mybatis.jar/ojdbc.jar、conf.xml、mapper.xml
2.(不同之处)
约定的目标: 省略掉statement,即根据约定 直接可以定位出SQL语句

a.接口,接口中的方法必须遵循以下约定:

  1. 方法名和mapper.xml文件中标签的id值相同
  2. 方法的 输入参数 和mapper.xml文件中标签的 parameterType类型一致 (如果mapper.xml的标签中没有 parameterType,则说明方法没有输入参数)
  3. 方法的返回值 和mapper.xml文件中标签的 resultType类型一致 (无论查询结果是一个 还是多个(student、List),在mapper.xml标签中的resultType中只写 一个(Student);如果没有resultType,则说明方法的返回值为void)

(List ),在mapper.xml标签中的resultType中只写 一个(Student);如果没有resultType,则说明方法的返回值为void)

package org.lanqiao.mapper;
import java.util.List;
import org.lanqiao.entity.Student;

//操作Mybatis的接口  需要和StudenetMapper.xml配置文件一个目录
public interface StudentMapper {

//		public abstract Student  queryStudentByStuno(int stuno);
		Student  queryStudentByStuno(int stuno);
		//查询全部
		List<Student> queryAllStudents();
		//增加
		void addStudentWithConverter(Student student);	
		
		void addStudent(Student student);
		//删除
		void deleteStudentByStuno(int stuno);
		
		//修改
		void updateStudentByStuno(Student student);
				
		Student queryStudentByStunoWithConverter(int stuno);

除了以上约定,要实现 接口中的方法 和 Mapper.xml中SQL标签一一对应,还需要以下1点:

  • namespace的值 ,就是 接口的全类名( 接口 - mapper.xml 一一对应)👴

匹配的过程:(约定的过程)

  1. 根据 接口名 找到 mapper.xml文件(根据的是namespace=接口全类名)
  2. 根据 接口的方法名 找到 mapper.xml文件中的SQL标签 (方法名=SQL标签Id值)

以上2点可以保证: 当我们调用接口中的方法时,程序能自动定位到 某一个Mapper.xml文件中的sqL标签

习惯:SQL映射文件(mapper.xml) 和 接口放在同一个包中 (注意修改conf.xml中加载mapper.xml文件的路径)

3.以上,可以通过接口的方法->SQL语句

执行:

StudentMapper studentMapper = session.getMapper(StudentMapper.class) ;
studentMapper.方法();

//可以通过build的第二参数 指定数据库环境
SqlSessionFactory sessionFacotry = new SqlSessionFactoryBuilder().build(reader,"development") ;
SqlSession session = sessionFacotry.openSession() ;

StudentMapper studentMapper = session.getMapper(StudentMapper.class) ;
Student student = studentMapper.queryStudentByStuno(2) ;//接口中的方法->SQL语句

System.out.println(student);
session.close();

通过session对象获取接口(session.getMapper(接口.class);),再调用该接口中的方法,程序会自动执行该方法对应的SQL。

四. 优化(属性文件,全局参数,别名,类型转换器,resultMap)

4.1 属性文件

可以将配置信息 单独放入 db.properties文件中,然后再动态引入

 db.properties:
	k=v
<configuration>
	<properties  resource="db.properties"/>
</configuration>

引入之后,使用${key}

4.2 MyBatis全局参数

在conf.xml中设置

<settings>
			<setting name="cacheEnabled" value="false"  />
			<setting name="lazyLoadingEnabled" value="false"  />
</settings> 

4.3 别名 conf.xml

<!-- 设置单个/多个别名 -->
	<typeAliases>
		<!-- 单个别名 (别名 忽略大小写) -->
		<typeAlias type="org.lanqiao.entity.Student" alias="student"/>
		<!--  批量定义别名  (别名 忽略大小写),以下会自动将该包中的所有类 批量定义别名: 别名就是类名(不带包名,忽略大小写)   -->
		<package name="org.lanqiao.entity"/>
	</typeAliases>

4.4 类型处理器(类型转换器)

1.MyBatis自带一些常见的类型处理器

  • int - number

2.自定义MyBatis类型处理器
java -数据库(jdbc类型)
示例:

  • 实体类Student : boolean stuSex
    true:男
    false:女

  • 表student: number stuSex
    1:男
    0:女

自定义类型转换器(boolean -number)步骤:

  • a.创建转换器:需要实现TypeHandler接口
    通过阅读源码发现,此接口有一个实现类 BaseTypeHandler ,因此 要实现转换器有2种选择:
    i.实现接口TypeHandler接口
    ii.继承BaseTypeHandler
  • b.配置conf.xml

4.5 resultMap可以实现2个功能:

1.类型转换
2.属性-字段的映射关系

<select id="queryStudentByStuno" 	parameterType="int"  	resultMap="studentMapping" >
	select * from student where stuno = #{stuno}
	<!--insert into student(stuno,stuname,stuage,graname,stusex) values(#{stuNo},#{stuName},#{stuAge},#{graName} ,#{stuSex ,javaType=boolean  ,jdbcType=INTEGER   } )-->
</select>
		
<resultMap type="student" id="studentMapping">
	<!-- 分为主键id 和非主键 result-->
	<id property="id"  column="stuno"  />
	<result property="stuName"  column="stuname" />
	<result property="stuAge"  column="stuage" />
	<result property="graName"  column="graname" />
	<result property="stuSex"  column="stusex"  javaType="boolean" jdbcType="INTEGER"/>
</resultMap>

五.输入参数和输出参数设置,存储过程

5.1 两种取值符号,ParameterType输入参数类型

1.类型为简单类型(8个基本类型+String)
#{} ${}

2.对比

#{}${}
#{任意值} 里面可以是任意值${value} 期中的表示符只能是value
#{}自动给String类型加上 ’ '(自动类型转换)${} 原样输出,但是适用于动态排列(动态字段)
#{} 可以防止SQL注入${} 不可防注入

相同:都可以获取对象的值,对象类型的时候,都需要${}#{} 写属性名

select stuno,stuname,stuage  from student where stuname = #{value}
select stuno,stuname,stuage  from student where stuname = '${value}'
动态排序:
select stuno,stuname,stuage  from student  order by ${value} asc

3.模糊查询

i.获取对象值:
模糊查询,方式一:
select stuno,stuname,stuage  from student where stuage= #{stuAge}  or stuname like #{stuName} 
			Student student = new Student();
 			student.setStuAge(24);
 			student.setStuName("%w%");
 			List<Student> students = studentMapper.queryStudentBystuageOrstuName(student) ;//接口的方法->SQL
 			
模糊查询,方式二:
	student.setStuName("w");
	select stuno,stuname,stuage  from student where stuage= #{stuAge}  or stuname like '%${stuName}%'

4.输入对象为HashMap:

where stuage= #{stuAge}  //xmlsql语句

Map<String,Object> studentMap = new HashMap();
studentMap.put("stuAge",24);
studentMap.put("stuName","zs");

List<Student> students = studentMapper.queryStudentBy(studentMap); 接口方法

用map中key的值 匹配 占位符#{stuAge},如果匹配成功 就用map的value替换占位符

5.2mybatis调用存储过程

1.查询某个年级的 学生总数
输入:年级
输出:该年级的学生总数

create or replace procedure queryCountByGradeWithProcedure(gName in varchar, scount out number )
as
begin 
	select count(*) into scount from student where graname = gname ;
end;
<select id="queryCountByGradeWithProcedure" statementType="CALLABLE"  parameterType="HashMap" >
	{
		CALL queryCountByGradeWithProcedure(
			#{gName,jdbcType=VARCHAR,mode=IN},
			#{scount,jdbcType=INTEGER,mode=OUT}
			--如果报错: No enum constant org.apache.ibatis.type.JdbcType.xx,则说明mybatis不支持xx类型,需要查表。
			--查Mybatis配置Mapping,javaType和JDBCType的对应关系。
		) 
	}	
</select>    
  • 其中 通过statementType="CALLABLE"设置SQL的执行方式是存储过程。 存储过程的输入参数gName需要通过HashMap来指定
    在使用时,通过hashmap的put方法传入输入参数的值;通过hashmap的Get方法 获取输出参数的值。
    要注意Jar问题:ojdbc6.jar不能在 调存储过程时 打回车、tab,但是ojdbc7.jar可以

5.3输出参数

1.输出参数为简单类型
在SQL配置文件中,使用resultType指定输出的参数类型。
一下指定输出类型为int:

<select id="querStudentsCount" resultType="int">
		select count(*) from student
</select>

2.输出参数为实体对象类型 (mapper动态代理CRUD)
3.输出参数为实体对象类型的集合

输出类型为集合,但是resultType依然写集合的元素类型(resultType="Student")

4.输出参数类型为HashMap
HashMap本身是一个集合,可以存放多个元素,
但是根据提示发现 返回值为HashMap时 ,查询的结果只能是1个学生(no,name);

  • 结论:一个HashMap 对应一个学生的多个元素(多个属性) 【一个map,一个学生】
    二维数组
    {
    {1,zs,23,xa}, -一个HashMap对象
    {2,ls,24,bj},
    {3,ww,25,tj}
    }

可以在HashMap上套一个集合返回多个map,从而返回多个学生信息。

5.resultType resultMap:实体类的属性、数据表的字段: 类型、名字不同时(stuno,id)

注意:当属性名 和字段名 不一致时,除了使用resultMap以外,还可以使用resultType+HashMap:

a.resultMap

<resultMap type="student" id="queryStudentByIdMap">
		<!-- 指定类中的属性 和 表中的字段 对应关系 -->
		<id property="stuNo"  column="id" />
		<result property="stuName" column="name" />
</resultMap>

b.resultType+HashMap
select 表的字段名 “类的属性名” from… 来制定字段名 和属性名的对应关系

<select id="queryStudentByIdWithHashMap" 	 parameterType="int"	resultType="student" >
	select id "stuNo",name "stuName" from student where id = #{id}
</select>

注意: 如果如果10个字段,但发现 某一个字段结果始终为默认值(0,0.0,null),则可能是 表的字段 和 类的属性名字写错。

六.动语态SQL

1.if使用,where使用

<select id="queryStuByNOrAWishSQLTag" 	 parameterType="student"	resultType="student" >
方法一:
	select stuno,stuname,stuage from student where 1=1
	<if test="stuName!=null and stuName!='' ">
		and stuname = #{stuName}
	</if>
	<if test="stuAge!=null and stuAge!=0 ">
		and stuage = #{stuAge}
	</if>
方法二(推荐):
	select stuno,stuname,stuage from student
	<where>(会自动处理第一个<if>标签中的 and,但不会处理之后<if>中的and)
		<if test="stuName!=null and stuName!='' ">
			and stuname = #{stuName}
		</if>
		<if test="stuAge!=null and stuAge!=0 ">
			and stuage = #{stuAge}
		</if>
	</where>
</select>

2.foreach使用
查询学号为1、2、53的学生信息

ids = {1,2,53};
select stuno,stuname from student where stuno in(1,2,53)

//java代码
List<Integer> stuNos = new ArrayList<>();
stuNos.add(1);
stuNos.add(2);
stuNos.add(53);
grade.setStuNos(stuNos);
List<Student> students = studentMapper.queryStudentsWithNosInGrade(grade);
xml代码,mapper
<select id="queryStudentsWithNosInGrade" parameterType="grade"	resultType="student" >
	select * from student
	<where>
		<if test="stuNos!=null and stuNos.size>0">
//collection="需要遍历的集合" open="条件前部分" close="条件后部分" item="遍历自定义变量" separator="变量分隔符号"
			<foreach collection="stuNos" open="and stuno in (" close=")" item="stuNo" separator=",">
				#{stuNo}
			</foreach>
		</if>
	</where>
</select>

2.1 迭代的类型:数组、对象数组、集合、属性(Grade类: List ids)

属性(Grade类: List<Integer> ids)
select * from student 
open:
select * from student and  stuno in (
item:
select * from student and  stuno in (1253
close:
select * from student and  stuno in (1,2,53)

简单类型的数组: 无论编写代码时,传递的是什么参数名(stuNos),在mapper.xml中 必须用array代替该数组

集合:无论编写代码时,传递的是什么参数名(stuNos),在mapper.xml中 必须用list代替该数组

对象数组: Student[] students = {student0,student1,student2} 每个studentx包含一个学号属性
注意的几点:

parameterType="Object[]"  第一点
 	<foreach collection="array" open=" and  stuno in (" close=")"  第二点
  		 		item="student" separator=",">   
  		 		#{student.stuNo}    第三点
  	</foreach>

3.调用sql语句

<sql id = "objctArrayStunos">
	xml里面的sql语句
</sql>
	<select id="方法名" parameterType="" resultType="">
		<include refid="需要调用的文件名.id"
	</select>	
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值