MyBatis学习总结二
MyBatis封装类
界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
数据访问层: 就是访问数据库, 执行对数据的查询,修改,删除等等的。
三层对应的包
界面层: controller包 (servlet)
业务逻辑层: service 包(XXXService类)
数据访问层: dao包(XXXDao类)
三层中类的交互
用户使用界面层–> 业务逻辑层—>数据访问层(持久层)–>数据库(mysql)
三层对应的处理框架
界面层—servlet—springmvc(框架)
业务逻辑层—service类–spring(框架)
数据访问层—dao类–mybatis(框架)
模版:
1. 规定了好一些条款,内容。
2. 加入自己的东西
框架特点:
1. 框架一般不是全能的, 不能做所有事情
2. 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
3. 框架是一个软件
介绍: 一个框架,早期叫做ibatis, 代码在github。
mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
(1)sql mapper :sql映射
可以把数据库表中的一行数据 映射为 一个java对象。
一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据
(2) Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。
mybatis提供了哪些功能:
开发人员做的是: 提供sql语句
最后是: 开发人员提供sql语句–mybatis处理sql—开发人员得到List集合或java对象(表中的数据)
总结:
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行。
1.配置mybatis
(1)conf.xml:配置数据库信息 和 需要加载的映射文件
表 - 类
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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 :增删改查标签
<mapper namespace="org.lanqiao.entity.personMapper">
<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();
}
原则:约定优于配置
硬编码方式
abc.java
Configuration conf = new Configuration();
con.setName(“myProject”) ;
配置方式:
abc.xml
myProject
约定:默认值就是myProject
1.基础环境:mybatis.jar/ojdbc.jar、conf.xml、mapper.xml
2.(不同之处)
约定的目标: 省略掉statement,即根据约定 直接可以定位出SQL语句
a.接口,接口中的方法必须遵循以下约定:
(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点:
匹配的过程:(约定的过程)
以上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。
可以将配置信息 单独放入 db.properties文件中,然后再动态引入
db.properties:
k=v
<configuration>
<properties resource="db.properties"/>
configuration>
引入之后,使用${key}
在conf.xml中设置
<settings>
<setting name="cacheEnabled" value="false" />
<setting name="lazyLoadingEnabled" value="false" />
settings>
<typeAliases>
<typeAlias type="org.lanqiao.entity.Student" alias="student"/>
<package name="org.lanqiao.entity"/>
typeAliases>
1.MyBatis自带一些常见的类型处理器
2.自定义MyBatis类型处理器
java -数据库(jdbc类型)
示例:
实体类Student : boolean stuSex
true:男
false:女
表student: number stuSex
1:男
0:女
自定义类型转换器(boolean -number)步骤:
1.类型转换
2.属性-字段的映射关系
<select id="queryStudentByStuno" parameterType="int" resultMap="studentMapping" >
select * from student where stuno = #{stuno}
select>
<resultMap type="student" id="studentMapping">
<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>
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替换占位符
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>
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,从而返回多个学生信息。
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),则可能是 表的字段 和 类的属性名字写错。
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 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语句
xml里面的sql语句
sql>
<select id="方法名" parameterType="" resultType="">
select>