文章目录
框架
- 半成品软件
- SSM
- spring
- 解决业务层问题
- mybatis
- 解决持久层问题
- springmvc
- 解决表现层问题
- spring
使用框架的好处
- 框架封装了很多的细节,使开发者可以使用极其简便的方式去实现功能,大大提高了开发的效率
三层架构
表现层
也就是web层:
它负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求web层,web需要接收http请求,完成http响应。
表现层包括展示层和控制层:
* 控制层负责接收请求,展示层负责结果的展示。
* 表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。表现层的设计一般都使用MVC模型。(MVC是表现层的设计模型,和其他层没有关系)
业务层
也就是service层:
它负责业务逻辑处理,和我们开发项目的需求息息相关。
web层依赖业务层,但是业务层不依赖web层。
业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性。(所以说,事务应该放到业务层来控制)
持久层
也就是dao层:
负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进行持久化的载体,数据访问层是业务层和持久层交互的接口
业务层需要通过数据访问层将数据持久化到数据库中。通俗的讲,持久层就是和数据库交互,对数据库表进行曾删改查的。
Mybatis
mybatis的环境搭建
- 创建模块导入依赖
- 创建实体类和dao接口
- 创建主配置文件
- 创建映射配置文件
<?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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql"> <!--default和id保持一致-->
<environment id="mysql">
<!--配置事务-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/guodb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件,通过dao的配置文件找到需要执行的sql语句-->
<mappers>
<mapper resource="com/guoguo/dao/IUserDao.xml"></mapper>
</mappers>
<!--指定映射配置文件,注解方式执行sql,不再是用resource而是class属性,属性性要写dao的全限定类名-->
<mappers>
<mapper class="com.guoguo.dao.IUserDao"></mapper>
</mappers>
</configuration>
mybatis环境搭建的注意事项
- 创建映射配置文件(Xxx.xml)和dao接口(XxxDao.java)的名称要保持一致
- mybatis把持久层接口名称和映射文件也叫做mapper
- 在idea创建目录的时候,它和包名称不一样,是一级目录,需要逐个创建
- mybatis的映射配置文件必须和dao接口包结构相同
- 映射文件的namespace属性必须是dao接口的全限定类名
- 底层利用反射创建动态代理对象
- 映射文件的操作标签的id属性值必须与dao接口的方法名相同
- 指定结果集类型,表示查询出来的结果要封装到哪里。resultTyle = “全限定类名”
只要遵循了3.4.5,那么我们就无需写dao的实现类
基于配置文件的crud
主配置文件
<?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">
<!--Mybatis的主配置文件-->
<configuration>
<!--配置环境-->
<environments default="mysql"> <!--default和id保持一致-->
<environment id="mysql">
<!--配置事务-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/guodb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件-->
<mappers>
<mapper resource="com/guoguo/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
映射配置文件
<?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.guoguo.dao.IUserDao">
<select id="findAll" resultType="com.guoguo.domain.User">
select * from USER ;
</select>
<insert id="save" parameterType="com.guoguo.domain.User">
insert into user(username,sex,address,birthday) values (#{username},#{sex},#{address},#{birthday});
</insert>
<update id="update" parameterType="com.guoguo.domain.User">
update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id =#{id}
</update>
<delete id="delete" parameterType="java.lang.Integer">
delete from user where id = #{id};
</delete>
</mapper>
返回新增用户的ID
keyColumn
属性:数据库表中的字段名keyProperty
属性:实体类的属性名resultType
属性:返回的结果类型order
属性:在插入语句的位置,(BEFORE)前/(AFTER)后
<insert id="updateAndResouceID" parameterType="com.guo.domain.User">
<selectKey keyColumn="id" keyProperty="id" resultType="java.lang.Integer" order="AFTER">
select last_insert_id();
</selectKey>
insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}) ;
</insert>
@Test
public void test05_insertResouceId(){
User user = new User();
user.setUsername("二娃");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("成都");
Integer id = dao.updateAndResouceID(user);
System.out.println("id="+user.getId());
}
模糊查询
- 方式一:编写sql时体现
<!--模糊查询-->
<select id="findByNameLike" resultType="com.guoguo.domain.User" parameterType="java.lang.String">
select * from user where username like '%${value}%';
</select>
@Test
public void test05findByNameLike(){
IUserDao dao = sqlSession.getMapper(IUserDao.class);
List<User> list = dao.findByNameLike("王");
for (User user : list) {
System.out.println(user);
}
}
- 方式二:传入参数时体现
<select id="findByNameLike" resultType="com.guoguo.domain.User" parameterType="java.lang.String">
select * from user where username like #{username};
</select>
@Test
public void test05findByNameLike(){
IUserDao dao = sqlSession.getMapper(IUserDao.class);
List<User> list = dao.findByNameLike("%王%");
for (User user : list) {
System.out.println(user);
}
}
区别
-
#{}表示一个占位符号
- 能过#{}可以实现preparedStatement向占位符中设置 值 ,自动进行jaa类型和jdbc类型转,
#{}
可以有效防止sql注入。#{}
可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}
括号中可以是value或是其它名称
- 能过#{}可以实现preparedStatement向占位符中设置 值 ,自动进行jaa类型和jdbc类型转,
-
${}表示拼接sql串
- 能过
${}
可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,${}
可以接收简单类型或pojo属性值,如果parameterType传输单个简单类型值,${}
括号中只能写value。
- 能过
实体类属性和数据库字段不一致的两种解决方案
-
sql语句层面解决:
- xml配置文件中的sql语句中,给数据库字段取别名,别名与实体类属性保持一致
-
配置文件层面解决:
<resultMap>
标签:type
属性:查询后返回值所要映射的实体类- *子标签
<id>
,<result>
:column属性:数据库字段名,property属性:实体类属性名
- *子标签
给实体类取别名
<!--给实体类取别名-->
<typeAliases>
<!--单个指定-->
<!--<typeAlias type="com.guo.domain.User" alias="user"></typeAlias>-->
<!--批量指定-->
<package name="com.guo.domain"></package>
</typeAliases>
Mybatis的事务控制
- 在业务层进行事务控制
动态sql
条件查询
<!--条件查询-->
<select id="findUserByCondition" resultMap="map" parameterType="user">
select * from USER
<where>
<if test="username != null and username!= ''">
and username like #{username}
</if>
<if test="id != 0">
or id = #{id}
</if>
</where>
</select>
根据多个id查询
<!--根据多个id查询-->
<select id="findUserByIds" resultMap="map" parameterType="queryvo">
select * from USER
<where>
<if test="ids != null and ids.length > 0">
<foreach collection="ids" open="id in (" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
</select>
抽取sql片断
<!--抽取sql片断-->
<sql id="defaultSql">
select * from user
</sql>
<select id="findUserByIds" resultMap="map" parameterType="queryvo">
<!--引入sql片断-->
<include refid="defaultSql"></include>
...
</select>
mybatis基于注解的使用】
- 不需要dao的xml配置文件,直接在dao接口的方法上使用@Select注解,在属性中定义sql语句
- 同时,需要将SqlMapConfig.xml文件中的mapper标签使用class属性,值为接口的全限定类名
多表查询
一对一(多对一)
- 主表的实体类中创建属性为:其它关联表的实体类
- xxxDao.xml文件中的映射
<resultMap>
映射标签内,加<association>
标签- property属性为:主表实体类变量:所关联表类名
- javaType属性为:所关联表实体类类名
多对多或一对多
- 主表的实体类中创建属性为:其它关联表的实体的List集合
- xxxDao.xml文件中的映射
<resultMap>
映射标签内,加<collection>
标签- property属性为:主表实体类变量 :关联表实体类的集合名
- ofType属性为:所关联表实体类类名
- 如果,主表和关联表有字段名相同,那么要修改基中一个字段名,取别名,防止结果集覆盖。取别名后,resultMap中的column的值也要保持一致
优化策略
- 为了提高服务器的性能和缓解服务器的压力,Mybatis提供了两种优化策略,分别是延迟加载和缓存机制
延迟加载
<!--延迟加载-->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
缓存
一级缓存
- 一级缓存是sqlSession级别的缓存,自带,无需手动开启
- 一级缓存随sqlSession的释放而关闭,或者执行update等非查询操作后关闭
二级缓存
- 二级缓存是sqlSessionFactory级别的缓存,需要在主配置文件中设置相关标签开启
<!--开启二级缓存-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
Spring
-
优势
- 方便解耦,简化开发
- 声明式事务的支持
- 方便集成各种优秀的框架
-
spring的两大核心 IOC、 AOP
- ioc 控制反转
- 把创建对象的权利交给框架。包括依赖注入(DI),和依赖查找
- 底层:Map
- di 依赖注入
- aop 面向切面
- 底层:动态代理
- 事物控制
- 声明式事务:配置文件进行实现 简化开发 维护方便
- 编程式事务:写代码 维护不方便
- 日志记录
- 埋点
- 数据采集
- ioc 控制反转
-
spring集成了junit ,mybatis没有
- junit --> runner运行器 一开始就没有帮你加载mybatis配置文件的功能
- 好处:junit – runner – springrunner – 在使用junit的时候帮肋我们加载配置文件 – 窗口也就有了
IOC 控制反转
前言:
* 容器的概念
* 控制反转
* 作用:降低耦合
* 耦合:
* 程序之间的依赖
* 类与类之间的依赖
* 方法之间的依赖
* 解耦:
* 降低程序之间的依赖:将编译期依赖转化为运行期依赖
* 解耦的思想:
* 利用反射技术创建对象
* 将配置信息定义在配置文件中
* 解耦的方式
* 配置文件
* 工厂模式:一个可以创建bean对象的工厂
* bean对象:可重用组件
* javabean:用java语言编写的可重用组件
- 概念:当前类将创建对象的权利交给了框架,称之为控制反转,它包括了依赖注入DI和依赖查找
- 作用:降低程序之间的耦合,降低代码之间的依赖
容器
- BeanFactory
- 顶层接口:多例,懒加载(什么时候使用它,什么时候创建对象)
- ApplicationContext(首选)
- BeanFactory的子接口:单例,立即加载( 一读取配置文件就创建对象)
- 三个实现类:
1. ClassPathXmlApplicationContext
//表示加载类路径下的配置文件 一定要放在类路径下
2. FileSystemXmlApplicationContext
//配置可以放在任意路径下,但是参数中要写绝对路径
3. AnnotationConfigApplicationContext
//当我们使用注解配置容器对象时,需要使用此类来创建spring容器,它用来读取注解
bean的创建方式
<!--如果是默认构造方法-->
<bean id="accountService" class="com.guoguo.dao.impl.AccountServiceImpl"></bean>
<!--使用普通工厂的方法创建对象(使用某个类中的方法创建对象),并存入spring容器-->
<bean id="instanceFactory" class="com.guoguo.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getaccountService"></bean>
<!--使用静态工厂的静态方法创建对象(使用某个类的静态方法创建对象),并存入spring容器-->
<bean id="accountService" class="com.guoguo.factory.StaticFactory" factory-method="getaccountService"></bean>
bean的作用范围
- 通过
scope
属性来指定作用范围
- singleton
- 默认 单例
- prototype
- 多例
- session
- 作用于web应用的请求范围
- request
- 作用于web应用的会话范围
- globalsession
- 作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是 session
bean的生命周期
-
单例:单例对象的生命周期和容器相同
- 创建:随容器的创建而创建
- 活着:容器还在对象就还在
- 死亡:容器销毁它就被销毁
-
多例:
- 创建:当需要使用对象时,spring为我们创建
- 活着:一直使用就一直活着
- 死亡:当对象长时间不使用时,由java的垃圾回收器回收
DI 依赖注入
- 维护类与类之间的依赖关系
注入的数据类型
- 基本类型和String类型
- 其它bean类型(在配置文件或者注解配置过的bean)
- 复杂类型与集合
注入的方式
1.通过构造函数注入
- 依靠
<constructor-arg>
标签-
出现的位置:bean标签内部
-
属性:
-
name:指定要注入的数据的名称
-
index:指定要注入的数据的索引,与构造函数的参数顺序一一对应,索引从0开始
-
type: 指定要注入的数据的数据类型
-
value:注入的数据的值,可提供基本数据类型和String类型数据,并且支持中文
-
ref:引入其它的bean对象(在spring的IOC核心容器中出现过的bean对象,换句话说就是在xml配置文件中
<bean>
标签配置过的对象),属性值为其它bean对象的id值
-
总结:type index name 属性都是在找给谁赋值,value ref 在给数据
优