1. 三层架构
-
界面层:和用户交互,调用业务逻辑层进行功能处理,显示请求的处理结果
-
业务逻辑层:接收传递的数据,完成业务逻辑;向上为界面层提供处理结果,向下问数据访问层要数据
-
数据访问层:和数据库交互,向上提供数据
不可跨层
2.常用的框架SSM
- Spring:是整合其他框架的框架,核心是IOC(控制翻转)和AOP(面向切面编程),它由20多个模块构成(大佬)。
- SpringMVC:Spring家族的一员,专门用来优化控制器(Servlet)的,提供了极简的数据提交、数据携带、页面跳转等功能。
- MyBatis:是持久化层(就是数据访问层)的一个框架,用来进行数据库访问的优化,专注Sql语句,极简化JDBC的访问。
3.什么是框架
它是一个半成品软件,将所有的公共的、重复的功能解决掉,帮助程序快速高效的进行开发,它是可复用的,可扩展的。
4.MyBatis框架
-
原是Apache的开源项目iBatis,2010迁移到Google code 改名为MyBatis,2013年迁移Git是基于Java的持久层框架。
-
主要解决的问题:
减轻JDBC的复杂性,直接使用java对象表示结果数据,让开发者更专注SQL的处理,其他工作由MyBatis完成。
5.Mybatis框架结构

6.添加框架步骤
-
)添加依赖
-
)添加配置文件
具体步骤:
- 新建库、表
- 新建maven项目,quickstart模板
- 修改目录,添加缺失目录和属性
- 修改pom.xml,添加Mybatis依赖、mysql依赖、添加资源文件指定
- 在idear中添加数据库的可视化
- 添加jdbc.properties数据库配置文件
- 添加SqlMapConfig.xml文件(MYbatis的核心配置文件)
- 添加完成表增删改查的功能配置文件StudentMapper.xml
- 创建测试类 测试
7.代码实现
-
配置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> <!--读取属性文件jdbc.properties resource:从resource资源目录下找对应文件加载 url:绝对路径D:\cd...--> <properties resource="jdbc.properties"></properties> <!-- 配置数据库的环境变量(连接配置)--> <environments default="development"> <!-- 开发时在公司使用的--> <environment id="development"> <!-- 配置事务管理器 type:事务管理的方式 JDBC:事务的控制交给程序员处理 MANAGED: 由容器(Spring)来管理事务--> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源 type:指定不同的配置方式 JNDI:java命名目录接口,在服务器端进行数据库连接池的管理 POOLED:使用数据库连接池 UNPOOLED:不使用数据库连接池--> <dataSource type="POOLED"> <!-- 配置数据库的基本参数 private String driver; private String url; private String username; private String password;--> <property name="driver" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> <!-- 回家的配置,直接改environments default来切换--> <!-- <environment id="home">--> <!-- <transactionManager type=""></transactionManager>--> <!-- <dataSource type=""></dataSource>--> <!-- </environment>--> </environments> <!-- 注册mapper.xml文件--> <mappers> <mapper resource="StudentMapper.xml"></mapper> </mappers> </configuration> -
配置mapper.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"> <!--namespace:指定命名空间(相当于包名)用来区 分不同mapper.xml文件中相同的id属性--> <mapper namespace="jv"> <!-- 查询, resultType:指定查询返回的结果集的类型,如果是集合则必须是泛型的类型 parameterType:如果有参数这通过它来指定参数的类型 --> <!-- 查询所有学生--> <select id="getAll" resultType="com.jv.pojo.Student"> select id,name,email,age from student; </select> <select id="getByid" parameterType="int" resultType="com.jv.pojo.Student"> select id,name,email,age from student where id =#{id} ; </select> <!-- 按名称模糊查询--> <select id="getByname" parameterType="string" resultType="com.jv.pojo.Student"> select id,name,email,age from student where name like '%${name}%'; </select> <!-- 增加学生--> <insert id="addStudent" parameterType="com.jv.pojo.Student" > insert into student (name,email,age) values (#{name},#{email},#{age}); </insert> <!-- 删除学生--> <delete id="delStudent" parameterType="int"> delete from student where id = #{id}; </delete> <!-- 更新学生--> <update id="update" parameterType="com.jv.pojo.Student"> update student set name = #{name},email=#{email},age=#{age} where id=#{id}; </update> </mapper> -
使用代码测试 完成查询所有
//使用文件流读取核心配置文件SqlMapConfig.xml InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); //创建SqlSessionFactory工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //取出SqlSession对象 SqlSession sqlSession = factory.openSession(); //完成查询 List<Object> list = sqlSession.selectList("jv.getAll"); // list.forEach(student -> System.out.println(student));//lambda表达式 for (Object o : list) { System.out.println(o); } //关闭SqlSession sqlSession.close(); -
切记:所有的增删改的操作后都必须手工提交事务!!sqlSession.commit();
8.MyBatis对象分析
-
Resources类
解析SqlMapConfig.xml文件,创建出相应的对象
InputStream in = Resources.getResourceAsStream(“SqlMapConfig.xml”);
-
SqlSessionFactory接口
创建SqlSessionFactory工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
-
SqlSession接口
完成sql功能的接口
9.测试注解
- @Test //测试方法
- @Before //在Test方法执行前先执行的代码
- @After // 在Test方法执行后先执行的代码
10.实体类(pojo)注册别名
-
单个注册
<!--注册实体类的别名--> <typeAliases> <!-- 单个实体类(pojo)注册--> <typeAlias type="com.jv.pojo.Student" alias="student"></typeAlias> </typeAliases> 实体类别名为student -
批量注册
<typeAliases> <!-- 实体类批量注册别名 别名是类名的驼峰命名法 --> <package name="com.jv.pojo"/> </typeAliases>使用别名注册后再map中就只用写别名:
<select id="getAll" resultType="student"> select id,name,email,age from student; </select>
11.动态代理存在的意义
在三层架构中 业务逻辑层要通过接口访问数据访问层的功能,动态代理可以实现。
动态代理的实现规范:
- UserMapper.xml和UserMapper.java的接口必须在同一个目录下
- UserMapper.xml和UserMapper.java的文件名必须一致,后缀不管
- UserMapper.xml文件标签的id值和UserMapper.java的接口中方法的名称完全一致
- UserMapper.xml文件标签的parameterTyper属性值和UserMapper.java的接口中方法的参数类型完全一致
- UserMapper.xml文件标签的resultTyper属性值和UserMapper.java的接口中方法的返回值类型完全一致
- UserMapper.xml文件中namespace属性必须是接口的完全限定名称. com.jv.—
- 在sqlMapConfig.xml文件中注册mapper时,使用class=接口的完全限定名。
12.批量注册mapper
<mappers>
<!-- <mapper class="com.jv.mapper.UsersMapper"></mapper>-->
<!-- 批量注册-->
<package name="com.jv.mapper"/>
</mappers>
13.#{ }占位符
传参大部分使用#{ }占位符,它底层是prepareStatement对象,是安全的数据库访问防止sqsl注入。
#{ }里怎么写 要看prepareStatement参数的类型
- prepareStatement类型是简单类型(8种基本和封装+String),则#{ }里随便写
- prepareStatement类型是实体类的类型,则#{ } 里只能是类中成员变量的名称(属性名),而且区分大小写。
14.${ }字符串拼接或字符串替换
-
字符串拼接,一般用于模糊查询中,建议少用有sql注入风险
同样看prepareStatement参数的类型
- prepareStatement参数的类型是简单类型,则${}里随便写,但分版本,3.5.1以下的只能写value
- prepareStatement参数的类型是实体类类型,则${}里只能是类中成员变量的名称(属性名),而且区分大小写。
优化模糊查询
传统:
select id,username,birthday,sex,address from users where username like '%${name}%';用concat函数字符串拼接加#{}:
select id,username,birthday,sex,address from users where username like concat('%',#{name},'%');
2.字符串替换
使用场景:当你需要根据不同的列名来进行对应的模糊查询时,用上${}字符串替换
-
mapper接口中可用iBatis注解 @Param来标记传参,在mapper中配置sql时调用
//模糊地址和用户名查询 List<Users> getByNameOrAddress( @Param("columnName")//模糊查询的列名 String columnName, @Param("columnValue")//模糊查询的值 String columnValue);-
mapper.xml中调用,${columnName}实现接收各种的列名 (#{}是占位符相当于 ?不可用在where后表示列名,因此要字符串替换)
<select id="getByNameOrAddress" resultType="users"> select id,username,birthday,sex,address from users where ${columnName} like concat('%',#{columnValue},'%'); </select>
-
15.返回自增的主键值
在插入语句结束后,返回自增的主键值到入参的users对象的id属性中。select last_insert_id();
<insert id="addUser" parameterType="users">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into users(username,birthday,sex,address) values (#{userName},#{birthday},#{sex},#{address})
</insert>
标签参数:
-
keyProperty:users对象的哪个属性来接返回的主键值
-
resultType:返回的主键类型
-
order:在插入语句执行前,还是插入执行后返回的主键值
16.UUID
是一个全球唯一字符串,由36个字母数字中划线组成。java和mysql都提供了UUID的生成。
17.什么是动态SQL
可以定义代码片段,可进行逻辑判断,可以进行循环处理(批量),是条件判断更简单。
-
:用来定义代码片段,可将所有的列名,或复杂的条件定义为代码片段供使用时调用
<!-- 定义代码片段--> <sql id="allColumns"> id,username,birthday,sex,address </sql> -
:用来引用定义的代码片段
select <include refid="allColumns"></include> from users -
:进行条件判断
-
:进行多个条件拼接,在查询、删除、更新中使用
<select id="QueryByCondition" parameterType="users" resultType="users"> select <include refid="allColumns"></include> from users <where> <if test="userName != null and userName != ''"> and username like concat('%',#{userName},'%') </if> <if test="birthday != null"> and birthday = #{birthday} </if> <if test="sex != null and sex != ''"> and sex = #{sex} </if> <if test="address != null and address != ''"> and address like concat('%',#{address},'%') </if> </where> </select> -
:有选择的进行更新处理,但至少更新一列
<update id="update" parameterType="users"> update users <set> <if test="userName != null and userName != ''"> username = #{userName}, </if> <if test="birthday != null"> birthday = #{birthday}, </if> <if test="sex != null and sex != ''"> sex = #{sex}, </if> <if test="address != null and address != '' "> address = #{address}, </if> </set> where id = #{id} </update> -
:用来进行循环遍历,完成循环条件查询、批量删除、批量添加、批量更新
//循环实现 :in(2,4,6)
<select id="getByIds" resultType="users"> select <include refid="allColumns"></include> from users where id in <foreach collection="array" item="id" separator="," open="(" close=")"> #{id} </foreach> </select>其中参数:
- collection:指定入参的类型,List集合用list、Map集合用map、数据用array.
- item:每次循环出来的值或对象
- separator:多个值或对象或语句之间的分隔符
- open:整个循环外的前括号
- close:整个循环外的后括号
注意:多条语句一次性执行一定要开启数据库批处理(如批量更新),在properties数据库配置文件中url上添加&allowMultiQueries=true
18.指定参数位置
如果入参是多个的,可以通过指定参数位置进行传参,是实体类包含不住的条件(实体类只能封装住成员变量的条件),如果某个成员变量要有区间范围类的判断,或者有两个值进行处理则实体类包不住,如:查询指定日期范围内的用户信息。
//查询指定日期范围的用户信息
List<Users> queryByBirthday(Date begin,Date end);
用arg0|arg1来去,默认第一个入参是0一次往后
<select id="queryByBirthday" resultType="users">
select <include refid="allColumns"></include>
from users
where birthday between #{arg0} and #{arg1};
</select>
19.入参是map
如果是入参数超过一个,使用map封装查询条件,更有语义,查询条件更明确。
map.put("birBegin",sf.parse("1995-1-1"));
map.put("birEnd",sf.parse("1999-12-31"));
<!-- #{birBegin}:就是map中的key-->
<select id="queryByMap" resultType="users">
select <include refid="allColumns"></include>
from users
where birthday between #{birBegin} and #{birEnd};
</select>
20.返回值是map
如果返回的数据实体类无法包含,可使用map返回多张表中的若干个数据,返回后这些数据之间没有任何关系就是object类型;返回的map中key就是列名或别名。
Map getReturnMap(Integer id);//接口
//测试方法中
Map returnMap = mapper.getReturnMap(15);
System.out.println(returnMap.get("username"));//username就是列名
<select id="getReturnMap" resultType="map">
select username,address from users where id = #{id};
</select>
546

被折叠的 条评论
为什么被折叠?



