文章目录
三层架构
三层架构包含的三层:
界面层,业务逻辑层,数据访问层
- 三层的职责
- 界面层:主要功能室接受用户的数据,显示请求的处理结果.使用web界面和用户交互,手机app也是标傲世承认那个的,用户在app中操作,业务逻辑在服务器端处理
- 业务逻辑层:接收传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据
- 数据访问层:与数据库打交道.主要实现对数据的增删改查.将数据在数据库中的数据提交给业务层,同时将业务层处理事务数据保存到数据库
三层对应的包:
- 页面层:controller
- 业务逻辑成:service包
- 数据访问层:dao包
三层中类的交互
用户使用界面层–>业务逻辑层–>数据访问层(持久层)–>数据库(mysql)
三层对应的处理框架
页面层-------servlet----springmvc
业务逻辑层------service类-------spring
数据访问层-------dao类---------mybatis
框架的概念
框架是一个模板
模板:
- 规定了一些条款,内容
- 加入自己的东西
框架是一些软件,半成品的软件,定义好了一些基础功能,需要加入你的功能就是完整的软件,它的基础功能室可重复使用的,可升级的
框架特点:
- 框架一般不是全能的,不能做所有事情
- 框架是针对某一个领域内有效,特长某一方面,比如mabatis做数据库操作强,但是不能做其他的
- 框架是一个软件
mybatis框架定义:
一个框架,早期叫做ibaatis,代码在github.
mybatis是mybatis SQL Mapper Framework for java(SQL映射框架)
-
sql mapper :sql映射
可以把数据库表中的一行数据,映射为一个java对象
一行数据可以看做一个java对象.操作这个对象,就相当于操作表中数据
-
dataaccess object (DAOs):数据访问,对数据库执行增删改查
mybatis提供了哪些功能:
- 提供了创建Connection,Statement,Resulset的能力,不用开发人员创建这些对象了
- 提供了执行sql语句的能力,不用你执行sql
- 提供了循环sql,把sql的结果转为java对象,List集合的能力
- 提供了关闭资源的能力,不用你关闭Connection,Statement,ResultSet
开发人员做的是:提供sql语句
最后是:开发人员提供sql语句–mybatis处理sql–开发人员得到list集合或者java对象
总结"mybatis是一个sql映射框架,提供的数据库的操作能力,增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建和销毁.
入门
下载mybatis
https://github.com/mybatis/mybatis-3/releases
mapper文件
<?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="com.bjpowernode.dao.StudentDao">
<select id="selectStudents" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student order by id
</select>
</mapper>
<!--
select:表示查询操作
id:你要执行的sql语句的唯一标识,mybatis会使用这个id的值来找到要执行的sql语句
可以自定义,但是要求你使用接口中的方法名称
resultTyoe:表示结果类型的,表示sql语句执行后得到的resultSet,遍历这个ResultSet得到的java对象的类型
值写的名称是全限定名称
-->
<!--
sql映射文件:写sql语句的,mybatis 执行这些sql
1.指定约束文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
mybatis-3-mapper.dtd:约束文件的名称,拓展名是dtd的
2.约束文件的作用:限制,检查当前文件中的标签,属性必须符合mybatis的要求.
3.mapper 是当前文件的根标签,必须的
namespace:叫做命名空间,唯一值得,可以是自定义的字符串
要求你使用dao接口的全限定名称.
4.在当前文件中,可以使用特定的标签,表示数据库的特定操作.
<select>:表示执行查询
<update>:表示更新数据库的操作,就是<update>标签中,写的是update sql语句
<insert>:表示插入
<delete>:表示删除
-->
mybatis文件
<?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>
<!--环境配置:数据库的连接信息
default值必须和某个environment的id值一样
告诉mybatis使用哪个数据库的连接信息,也就是访问哪个数据库
-->
<environments default="development">
<!--environments:一个数据库的配置,环境
id:一个唯一值,自定义的,表示一个环境的名称.
-->
<environment id="development">
<!--
transactionManager:mybatis的事务类型
type:JDBC(表示使用jdbc中Connection对象commit,rollback做事务处理)
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,连接数据库的
type:表示数据源的类型,POOLED表示使用连接池
-->
<dataSource type="POOLED">
<!--
dirver,url,username,password是固定的,不能自己改
-->
<!--数据库的驱动类名-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
<!--访问数据库的用户名称-->
<property name="username" value="root"/>
<!--访问数据库的用户密码-->
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--sql mapper(sql映射文件)的位置-->
<mappers>
<!--一个mapper标签指定一个文件的位置
从类路径开始的路径信息. (可以有多个)
-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
</mappers>
</configuration>
<!--
mybatis的主配置文件:主要定义了数据库的配置信息,sql配置文件的位置
1.约束文件的说明
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
mybatis-3-config.dtd:约束文件的名称
2.configuration
-->
问题:xml文件没有编译到target.classes下
首先检查pom.xml文件,查看是否有:
<build>
<resources>
<resource>
<directory>src/main/java</directory><!--所在目录-->
<includes><!--包括目录下面的.properties,.xml文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
-
确保文件夹是这种格式的
-
操作maven
- 重新构筑工程
- 清理缓存
这几步每次都尝试运行一下,运行成功后面就不需要了.
-
最终方式:上面几种都不行的话,直接拷贝到目标文件夹
mybatis调试日志
<!--控制mybatis全局行为的-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
主要类的介绍
-
Resources:mybatis中的一个类,负责读取主配置文件
InputStream in = Resources.getResourceAsStream(“mybatis.xml”)
-
SqlSessionFactoryBuilder:创建sqlSessionFactory对象,
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
-
SqlSessionFactory:重量级对象,程序创建一个对象耗时比较长,使用资源比较多.在整个的项目目中,有一个就够用了.
SqlSessionFactory:接口,接口实现类:DefaultSqlSessionFactory
SqlSessionFactory作用:获取SqlSession对象.
SqlSession SqlSession = factory.openSession();
openSession()方法说明:
-
openSession():无参数的,获取是非自动提交事务的SqlSession对象
-
openSession(boolean):
openSession(true) 获取自动提交事务的SqlSession
openSession(false) 获取非自动提交事务的SqlSession
-
-
SqlSession:
SqlSession接口:定义了操作数据的方法 例如seletctOne(),selectList(),insert(),update(),dalete(),commit(),rollback()
sqlSession接口的实现类,DefaultSqlSession,
使用要求:SqlSession对象不是线程安全的的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象,在执行完sql语句后,需要关闭它,执行SqlSession.close(),这样能保证它的使用是线程安全的.
动态代理条件分析
List studentList = dao.selectStudents();调用
-
dao对象,类型是studentDao,全限定名称是:com.bjpowernode.dao.StudentDao权限定名称和namespace是一样的
-
方法名称,selectStudents,这个方法就是mapper文件中的id值selectStudents
-
通过dao种方法的返回值也可以确定mybatis要调用的方法SqlSession方法
如果返回值是list,调用的是SqlSession.selectList()方法
如果返回值int,或是非list的,看mapper中的标签是,就会调用SqlSession对应的方法
-
mybatis的动态代理:mybatis根据dao的方法调用,获取执行sql语句的信息.mybatis根据你的dao接口,创建出一个dao接口的实现类,并创建这个类的的的对象,完成SqlSession调用方法,访问数据库
动态代理:
StudentDao dao = SqlSession.getMapper(dao接口.class)获取这个dao接口的对象
使用mybatis动态代理机制,使用SqlSession.getMapper(dao接口)
getMapper能获取dao接口对应的实现类对象
深入理解参数
从java代码中传入mapper文件的sql语句中
-
parameterType:mapper文件中的一个属性.表示dao接口中方法的参数的数据类型.例如StudentDao接口,并非强制的
-
简单类型:mybatis中吧java中基本参数类型和String类型叫做简单类型,在mapper文件获取简单类型的一个参数的值,使用#{任意字符}
-
传参原理:
/* 使用#{}之后,mybatis 执行sql语句是使用的jabc中的PreparedStatement对象 由mybatis执行以下代码 1.mybatis创建connection个,PreparedStatement对象 String SQL = "select id,name,email,age from student where id = ?" PrepareStatement pst = new PrepareStatement(sql); pst.setInt(1,1001); 2.执行sql封装为resultType = "com.bjpowernode.domain.Student"这个对象 ResultSet rs = ps.executeQuery(); while(rs.next()){ //从数据库中存储数据,并存储到java对象的属性中 } */
多个参数:
- 使用@Parm命名参数
接口 public List selectMulitParam(String name,Integer age)
使用 @Param(“参数名”) String name
mapper文件:
<select>
select * from student where name = #{myname} or age = #{myage}
</select>
-
使用对象方式传递
<!--多个参数,使用java对象的属性值,作为参数实际值 使用对象的语法:#{属性名,javaType=类型名称,jdbcType=数据类型} 很少用 javaType:指java中的属性数据类型 jdbcType:在数据库中的数据类型 例如:#{paramName,javaType = java.lang.String,jdbcType=VARCHAR} 一般我们使用简化方式:#{属性名},javaType,jdbcType的值mybatis通过反射能够获取.不需要提供 --> <select id="selectMultiObject" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where id = #{paramName,javaType=java.lang.String,jdbcType=VARCHAR} or age = #{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER} </select> 简化版 #{paramName}即可
-
按位置传参(了解)
-
map传参(可读性很差,不建议使用)
#和$
-
#:占位符:告诉mybatis使用实际的参数值代替.并使用PrepareStatiment对象执行sql语句,#{…}代替sql语句的?.这样做更加安全,更迅速
#的结果:select id,name,email,age from studetn where id = ?
-
** ∗ ∗ : ∗ ∗ 字 符 串 替 换 ∗ ∗ : 告 诉 m y b a t i s 使 用 **:**字符串替换**:告诉mybatis使用 ∗∗:∗∗字符串替换∗∗:告诉mybatis使用包含的"字符串"替换所在位置.使用Statement把sql语句和${}的内容连接起来.主要用在替换表名,列名,不同列排序等操作.
$的结果:select id,name,email,age from studetn where id = 1001
使用的是Statement对象执行sql,效率比PreparedStatement低
当你确定数据是安全的,可以使用$
#和$的区别(重点):
- #:使用?在sql语句中做占位的,使用PreparedStatement执行sql,效率高
- #:能够避免sql注入,更加安全
- $:不适用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
- $:有sql注入的风险,缺乏安全性.
- $:可以替换表名或者列名
封装mybatis输出结果
mybatis执行了sql语句,得到java对象
-
resultType结果类型,指sql语句执行完毕后,数据转为java对象
处理方式:
- mybatis执行sql语句,然后mybatis调用类的无参数构造方法,创建对象
- mybatis把ResultSet指定列值付给同名的属性
<select id="selectMutiPosotion" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student </select>
对等的JDBC:
ResultSet rs = executeQuery("select id,name,email,age from student"); while(rs.next()){ Student student = new Student(); student.setId(rs.getInt("id")); ... }
ResultType
-
resultType结果类型,指sql语句执行完毕后,数据转为java对象,java类型是任意的
resultType结果类型的它值,1.类型的全限定名称2.类型的别名,例如java.lang.Integer别名是int
-
定义自定义类型的别名
- 在mybatis主配置文件中定义,使定义别名
- 可以再resultType中使用自定义别名
<typeAliases> <!-- 可以制定一个类型一个自定义别名 type:自定义类型的全限定名称 alias:别名(短小,容易定义) --> <!-- <typeAlias type="com.bjpowernode.domain.Student" />--> <!-- <typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu"/>--> <!-- <package> name是包名,这个包中的所有类,类名就是别名(类名不区分大小写) --> <package name="com.bjpowernode.domain.Student"/> <package name="com.bjpowernode.vo.ViewStudent"/> </typeAliases>
-
resultMap:结果映射,指定列名和java对象的属性对应关系.
- 你自定义列值赋值给哪个属性
- 当你的列名和属性名不一样时,一定要使用resultMap
<resultMap id="studentMap" type="com.bjpowernode.domain.Student"> <!--列名和java属性之间的关系--> <!--主键列,使用id标签 cloumn:列名 property:java类型的属性名 --> <id column="id" property="id"/> <!--非主键列,使用result--> <result column="name" property="name"/> <result column="email" property="email"/> <result column="age" property="age"/> </resultMap> <select id="selectAllStudents" resultMap="studentMap"> select id,name,email,age from student </select>
resultMap是可以复用的.
resultMap和resultType不要一起用,二选一
-
使用resultType的不同属性的另一种方法,使用as起别名
like查询
- 提前准备好"%张%";
- 或者在mapper文件中准备好 “%” #{name} “%”
动态 SQL
-
动态sql:sql的内容是变化的,可以根据条件获取到不同的sql语句.
主要是where部分发生变化.
-
动态sql的实现,使用的是mybatis提供的标签,,
是判断条件的
语法:
部分SQL语句
-
用来包含多个的.当多个id有一个成立时,会自动增加一个where关键字,并去掉if中多余的 and or等.
-
循环Java中的数组,list集合的,主要用在sql的in语句中
比如学生id是 1001,1002,1003的三个学生
select * from student where id in (1001,1002,1003)
collection:表示接口中的方法参数的类型,如果是数组使用array,如果是list集合使用list
item:自定义的,表示数组和集合成员的变量
open:循环开始时的字符
close:循环结束时的字符
separator:集合成员之间的分割符
<!--foreach使用1--> <select id="selectForeachOne" resultType="com.bjpowernode.domain.Student"> select * from student where id in <foreach collection="list" item="myid" open="(" close=")" separator=","> #{myid} </foreach> </select> <select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student"> select * from student where id in <foreach collection="list" item ="stu" open="(" close=")" separator=","> #{stu.id} </foreach> </select>
对应的两个方法
@Test public void testselectStudentForeachOne() { SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); Student stu = new Student(1001, "张三", "zhangsan@126.com", 25); List<Integer> list = new ArrayList<>(); List<Student> student = dao.selectForeachOne(list); for (Student student1 : student) { System.out.println("foreach---one===" + student1); } } @Test public void testselectStudentForeachTwo() { SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); Student stu = new Student(1001); Student stu2 = new Student(1002); List<Student> list = new ArrayList<>(); list.add(stu); list.add(stu2); List<Student> student = dao.selectForeachTwo(list); for (Student student1 : student) { System.out.println("foreach---one===" + student1); } }
-
-
sql代码片段,就是复用一些语法
步骤:
- 先sql语句,表名,字段等
- 在使用即可
主配置文件
transactionManager:mybatis提交事务,回滚事务的方式
type:事务的处理的类型
- JDBC:表示mybatis底层是调用JDBC中Connection对象的,commit,rollback
- MANAGED:把mybatis的事务委托给其他的容器(一个服务器软件,一个框架(spring))
DataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源.数据源表示Connection对象的
type:指定数据源的类型
-
POOLED:使用连接池,mybatis回传件PooledDataSource类
-
UNPOOLED:在每一次执行sql语句的时候,先创建连接,执行sql,再关闭连接
mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
-
JNDI:java命名和目录服务(类似于windows注册表)
数据库的属性配置文件
把数据库的连接信息放到一个单独的文件中.和mybatis主配置文件分开,目的是便于修改,保存,处理多个数据库的信息
-
在resources目录中定义一个属性配置文件,xxxx.properties,例如jdbc.properties
在属性配置文件中,定义数据,格式是key=value
key:一般使用,做多级目录
例如:jdbc.mysql.driver , jdbc.driver ,mydriver
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql//…
-
在mybatis的主配置文件中,使用指定文件的位置,在需要使用值的地方,${key}
指定多个mapper文件的方式
-
标签写多个,有多少个就写多少个
-
使用包名
这个包中的所有xml文件都能一次加载进mybatis
使用package的要求:
- mapper文件名称需要和接口名称一致,并且区分大小写
- mapper文件和dao接口需要在同一目录
pageHelper
pageHelper是用来做数据分页的
需要导入PageHelper依赖
<!-- PageHelper依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
需要导入mybatis框架中
<!--配置插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
使用方法:
//加入pageHelper的方法,,分页
//pageNum:第几页,从1开始
//pageSize:一页中有多少行数据
PageHelper.startPage(2,2);
xml文件都能一次加载进mybatis
使用package的要求:
- mapper文件名称需要和接口名称一致,并且区分大小写
- mapper文件和dao接口需要在同一目录
pageHelper
pageHelper是用来做数据分页的
需要导入PageHelper依赖
<!-- PageHelper依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
需要导入mybatis框架中
<!--配置插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
使用方法:
//加入pageHelper的方法,,分页
//pageNum:第几页,从1开始
//pageSize:一页中有多少行数据
PageHelper.startPage(2,2);