springmvc+spring+mybatis 56课时 24k商城
ssm、maven、通用mapper、shiro(了解)、vue.js(掌握)
防止sql注入
mybatis
1.传统的jdbc
加载驱动
获取链接connection
获取预处理对象statement
设置sql(采用占位符,防止sql注入)
给占位符设置值
执行获取结果集
对结果集进行封装
释放资源
问题:
1.频繁的创建链接,释放资源 造成了系统资源浪费。----->数据库连接池
2.sql语句在java代码中,造成后期维护不易
3.占位符设置值,存在硬编码,where语句里 条件不固定,造成维护不易
4.对结果集的解析封装存在硬编码,
2.ORM简介
Object Relational Mapping :对象关系映射
简单的理解为:ORM是通过 使用描述对象和数据库库之间的映射关系的元数据,将程序中的 对象自动的持久化到关系型数据库中。
hibernate、mybatis
3.mybatis架构
mybatis是一个ORM框架,是一个基于java的持久层框架
mybatis会对jdbc的操作过程进行封装,使得开发者只需要关注SQL本身,而无需去花费精力去处理 注册驱动、获取链接、设置参数、结果集分析、释放资源等工作,可以简化jdbc开发成本。
mybatis.xml(全局配置文件,名字是不固定的)
作用:配置mybatis的运行环境,数据源/事物
mapper.xml:映射文件。sql语句 需要在全局配置文件中加载
sqlSessionFactory:会化工厂。根据全局配置文件来创建工厂,创建工厂
作用:创建会话的
sqlSession:会话。作用:操作数据库的
Executor(执行器):会话是通过执行器来操作数据库的
mapped statement :底层封装对象
作用:对操作数据库的过程进行封装,包括sql、输入参数、结果集
mysql数据库
输入参数类型:
java简单类型
pojo自定义对象
hashmap
输出结果类型:
java简单类型
pojo自定义对象
hashmap
4.mybatis环境搭建
- 新建java项目,导入jar包 mybatis-3.2.7.jar junit
- 配置log4j.properties打印日志
- 配置mybatis全局配置文件
<!-- 运行环境:与spring整合后就不需要了
default="" 运行哪个环境,里面是id
-->
<environments default="mysql">
<environment id="mysql">
<!-- 事务管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="111111"/>
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
5.入门案例
- pojo对象
- 映射文件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=""作用: 分割sql --> <mapper namespace="UserMapper"> <!-- 入门程序:根据id查询用户信息 id:唯一的(本namespace下唯一),用于标识映射文件的sql,称为statment的id paramentType:输入参数类型; 支持的类型包括java基本类型、pojo对象、hashmap resultType:输出结果类型; 指定的为单条记录的类型 #{}:占位符 注意:如果输入参数类型是基本类型,则#{}里面可以是任意参数。或者是#{value} --> <select id="selectById" parameterType="int" resultType="com.cbb.pojo.User"> select * from user where id = #{id} </select> </mapper>
- 测试用例
//1.加载mybatis的运行环境 io流的方法去读取全局配置文件 InputStream is =Resources.getResourceAsStream("mybatis.xml"); //2.创建会化工厂 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3.获取会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //4.操作数据库 //第一个参数:statement的id 具体执行的sql 写法是:namespace.id //第二个参数:值 User user = sqlSession.selectOne("UserMapper.selectById",1); System.out.println(user); sqlSession.close();//释放资源
JUnit Test
/**
* 在@Test方法执行前 执行,可以进行一些初始化的工作
*/
@Before
public void init(){
System.out.println("init。。。。。。。。");
}
/**
* 方法描述:JUnit Test
*/
@Test
public void name() {
System.out.println("执行了测试方法!");
}
/**
* 方法描述:在@Test注解方法执行后再执行
*/
@After
public void after(){
System.out.println("善后工作。。。。释放资源等等。。。。");
}
6.会话工厂与会话
SqlSessionFactory:会话工厂。通过全局配置文件创建的,由SqlSessionFactoryBuild对象创建。
- 作用:创建会话。
- 特点:会化工厂一旦创建,就会在应用程序的执行期间一直存在。我们就不需要重复的来创建这个会话工厂了。
- 所以我们应该把它的实现方式设计为 单例模式的 (而不是他自身就是单例模式的)
SqlSession:会话。作用:操作数据库。
- 特点:线程不安全的。应该把会话声明为局部的
7.全局配置文件的其他配置
起别名:
<!-- 起别名 -->
<typeAliases>
<!-- type:指的是要被定义别名的类的全限定名
alias:自定义的别名
-->
<typeAlias type="com.cbb.pojo.User" alias="user"/>
<!-- 批量起别名 name:包
会批量扫描包下所有类 然后批量的起别名。 别名为类名(首字母大写或者小写都可以,即起了两个别名)
-->
<package name="com.cbb.pojo"/>
</typeAliases>
加载外部资源:
<!-- 加载资源文件 -->
<properties resource="db.properties"></properties>
<property name="driver" value="${jdbc.driver}"/>
jdbc.driver=com.mysql.jdbc.Driver
作业-0307 我爱登录的t_user表 新增、修改、删除、 查询(根据名字模糊查询、查询出生日在2010年~2019年中间的用户,并 且2010和2019是通过占位符设置)
8.传统的dao开发方法
dao接口
daoImpl实现
映射文件
9.动态代理实现方式
dao接口
映射文件mapper.xml
只需要程序员编写Mapper接口(相当于dao接口),和映射文件,由mybatis框架根据 接口 来创建接口的动态代理对象,来代理接口方法的实现 (类似于传统dao开发方式中 的实现类)
规范要求:
- mapper.xml映射文件和mapper接口的名字必须一致。
- mapper.xml映射文件的namespace与接口的类全路径相同
- mapper.xml映射文件的statement的id与接口的方法名相同
- mapper.xml映射文件的参数类型parameterType与接口方法的参数类型相同
- mapper.xml映射文件的输出结果类型与接口方法的返回类型相同
<mappers>
<!-- 批量加载包下的 -->
<package name="com.cbb.mapper"/>
</mappers>
10.servlet与mybatis的整合
public class UserServiceImpl implements UserService{
private SqlSessionFactory factory = SqlSessionFactoryUtil.getSqlSessionFactory();//获取单例模式的会话工厂
@Override
public User selectById(int id) {
SqlSession session = factory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);//获取代理对象
User user = userMapper.selectById(id);//方法调用
session.close();//是否资源 如果是新增、修改、删除,关闭前记得要 调用 commit方法
return user;
}
}
作业-0308 我爱登录的项目。 加入mybatis框架来完成。 需要做的功能以下: 登录、注册、列表查询(根据,名字模糊查询所有)、用户表的新增、修改和删除
11.Mapper.xml详解
11.1.parameterType(输入类型)
java简单类型 int、String #{占位符的方式,任意字符}
pojo自定义对象 新增 #{pojo的属性名}
hashmap
<!-- hashmap用例
取值方式:#{map的key}
注意:当时用map中不存在的key取值时,取值为空null。代码此处不报错-->
<select id="selectByMap" parameterType="map" resultType="User">
select * from user where sex = #{sex} and address like concat("%",#{address},"%")
</select>
多参数的
/**
* 方法描述:多参数用例
* @param sex
* @param address
* @return
*/
//public List<User> selectByParams(@Param("sex")String sex, @Param("address")String address);
public List<User> selectByParams(String sex,String address);
<!-- 多参数的用例
parameterType 可以省略掉
@Param:作用:把注解的对象 set放到了map中,key就是("")
第二种取值方式:#{index},下标index 从0开始,-->
<select id="selectByParams" resultType="User">
<!-- select * from user where sex = #{sex} and address like concat("%",#{address},"%") -->
select * from user where sex = #{0} and address like concat("%",#{1},"%")
</select>
11.2resultType(输出类型)
java简单类型的
pojo自定义对象
hashmap
11.3resultMap
resultType:在指定pojo对象接受 映射的结果集时,需要将pojo对象的属性名 和数据库表的字段名要一致。
如果有不一致的,则查询的该字段为null
解决名字不一致的方法:
方案一:给sql查询的字段as别名
<!-- 方案一:给sql查询的字段 as 别名 ,别名和pojo对象的属性名一致 -->
<select id="selectAll" resultType="Car">
select carId carId,name carName,userId userId from car
</select>
方案二:使用resultMap
<!--
id:唯一的
type:把结果集映射到那个对象上
<id/>:结果集的主键 唯一标示
<result/>:结果集的 普通字段
column:表的字段名
property:pojo对象的属性名
column和property在一起表示 之间的映射关系
可以仅仅是写名字不一致的字段
-->
<resultMap type="Car" id="CarMap">
<id column="carId" property="carId"/>
<result column="name" property="carName"/>
<result column="userId" property="userId"/>
</resultMap>
<!--resultMap:对应自定义的哪个resultMap的id -->
<select id="selectAll" resultMap="CarMap">
select * from car
</select>
如果使用resultMap来处理这种简单的 名字不一致的问题的时候,可以在resultMap里 只去配置这个 名字不一致的字段
(<id> 或<result>),名字一致的可以省略掉。
resultMap:除了能解决上述的名字 不一致的问题外,还可以结果映射复杂的pojo问题
<resultMap type="UserVo" id="UserVoMap">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
<!-- 一对多集合
ofType:集合的类型-->
<collection property="cars" ofType="Car">
<id column="carId" property="carId"/>
<result column="name" property="carName"/>
<result column="userId" property="userId"/>
</collection>
</resultMap>
12.动态sql
通过mybatis提供的各种标签方法实现动态拼接sql。
if用例:
<!-- 动态sql:if用例
if:语句判断,<if test="">使用and进行的并
where:去除多余的and 或者是or
-->
<select id="selectIf" parameterType="map" resultType="User">
select * from user
<where>
<if test="sex!=null and sex!=''">
and sex = #{sex}
</if>
<if test="address!=null and address!=''">
and address like concat("%",#{address},"%")
</if>
</where>
</select>
set用例:
<!-- set :会去除多余的逗号-->
<update id="updateUser" parameterType="User">
update user
<set>
<if test="username!=null and username!=''">
username = #{username} ,
</if>
<if test="sex!=null and sex!=''">
sex = #{sex} ,
</if>
<if test="address!=null and address!=''">
address = #{address}
</if>
</set>
where id =#{id}
</update>
foreach遍历:
<!-- foreach:批量删除
collection:集合的类型。可以是list(list集合)还可以是array(数组)还可是map还可以pojo包装类中的属性名
item:循环中的当前对象
open:循环的开始
close:循环的结束
separator:分隔符
-->
<delete id="deleteBatch" parameterType="int">
delete from user where id in
<foreach collection="list" item="id11" open="(" close=")" separator=",">
#{id11}
</foreach>
</delete>
作业0311 我爱登录 1、列表查询(根据实际条件查询 )/2、批量删除(复选框 删除button)