1、Spring
1、管理Bean
Spring的IOC
容器管理Bean一共有两种方式,基于xml
文件和基于注解,其中基于注解是最常用的。
创建Bean实例:一共四个,四个的作用都是一样的创建Bean,只是意义不同。
-
@Component:基于注解创建Bean,用于创建一般的对象。以下三个注解都是它的子注解;
-
@Service:用于创建业务逻辑层Bean,Service层;
-
@Controller:用于创建表现层,接口层对象;
-
@Repository:用于创建数据层Bean定义;
-
@Scope("xxx"):和创建Bean的注解一起使用,用于声明对象域。
-
singleton
:单例,默认,全局只有一个实例; -
prototype
:多实例懒创建的,每次从容器中获取Bean的时候都新建一个。容易导致频繁GC; -
request
:同一个请求,每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP
请求内有效; -
session
:同一个会话级别。
-
属性注入:
-
@Autowired
:根据属性类型进行自动装配; -
@Qualifier(value = "userDaoImpl1")
:根据Bean名称进行注入。但是注意:@Qualifier使用时必须和@Autowired
一起使用。作用是区别多个同类型的Bean
; -
@Resource(name = "userDaoImpl1")
:既可以根据类型注入,也可以根据名称注入,这里是根据名称进行注入,如果不用name属性就是根据类型注入; -
@Value(value = "abc")
:注入基本数据类型属性,上述三个都是注入容器中的Bean属性,而这个是注入基本数据类型的属性。
配置类:
-
@Configuration
:作为配置类,替代xml
配置文件; -
@ComponentScan(basePackages = {"com.atguigu"})
:作用于配置类,配置包扫描路径,也就是配置要去识别哪个路径下的,声明Bean的注解; -
@Bean
:声明方法返回值为Bean,并注入容器中; -
@Value
注解也可用于为配置类中的基本属性赋值; -
条件注解:该注解可以定义在类上,一般使用在configuration配置类上,用于限制该配置类是否生效。也可以定义在方法上和@Bean组合使用,用于判断该bean是否需要注入;
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Configuration</span> <span style="color:#aa5500">// 表明这是一个配置类</span>
<span style="color:#555555">@ComponentScan</span>(<span style="color:#000000">basePackages</span> <span style="color:#981a1a">=</span> {<span style="color:#aa1111">"com.atguigu"</span>})
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">AppConfig</span> {
<span style="color:#555555">@Bean</span>(<span style="color:#000000">initMethod</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"init"</span>, <span style="color:#000000">destroyMethod</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"destroy"</span>) <span style="color:#aa5500">// 1、配置类中的方法使用@Bean注解,配置一个Bean实例放入IOC容器中,Bean名字就是方法名,效果和@Component类似。2、方法返回值就是实例对象。3、它也可作用于@Component及其子注解类的方法中。4、同时接受生命周期的方法回调。</span>
<span style="color:#770088">public</span> <span style="color:#000000">MyBean</span> <span style="color:#000000">myBean</span>(<span style="color:#000000">Student</span> <span style="color:#000000">stu</span>) { <span style="color:#aa5500">// 方法若有参数,需要自动从容器中获取,获取不到就报错</span>
<span style="color:#770088">return</span> <span style="color:#770088">new</span> <span style="color:#000000">MyBean</span>();
}
<span style="color:#555555">@Value</span>(<span style="color:#aa1111">"${app.database.url}"</span>)
<span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">databaseUrl</span>;
}</span></span>
2、AOP
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Component</span> <span style="color:#aa5500">// 该AOP类也要交给Spring管理</span>
<span style="color:#555555">@Aspect</span> <span style="color:#aa5500">// 表示该类是用于增强逻辑的</span>
<span style="color:#555555">@Order</span>(<span style="color:#116644">1</span>) <span style="color:#aa5500">// 多个增强类作用于一个方法时,可以设置优先级</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">UserProxy</span> {
<span style="color:#aa5500">//@Before 注解表示作为前置通知,value值是切点匹配</span>
<span style="color:#555555">@Before</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(* com.atguigu.spring5.aopanno.User.add(..))"</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">before</span>() {
<span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"before........."</span>);
}
<span style="color:#aa5500">//后置通知(返回通知)</span>
<span style="color:#555555">@AfterReturning</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(*com.atguigu.spring5.aopanno.User.add(..))"</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">afterReturning</span>() {
<span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"afterReturning........."</span>);
}
<span style="color:#aa5500">//最终通知</span>
<span style="color:#555555">@After</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(* com.atguigu.spring5.aopanno.User.add(..))"</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">after</span>() {
<span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"after........."</span>);
}
<span style="color:#aa5500">//异常通知:方法抛异常后执行</span>
<span style="color:#555555">@AfterThrowing</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(*com.atguigu.spring5.aopanno.User.add(..))"</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">afterThrowing</span>() {
<span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"afterThrowing........."</span>);
}
<span style="color:#aa5500">//环绕通知</span>
<span style="color:#555555">@Around</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(* com.atguigu.spring5.aopanno.User.add(..))"</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">around</span>(<span style="color:#000000">ProceedingJoinPoint</span> <span style="color:#000000">proceedingJoinPoint</span>) <span style="color:#770088">throws</span>
<span style="color:#000000">Throwable</span> {
<span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"环绕之前........."</span>);
<span style="color:#aa5500">//原始方法执行</span>
<span style="color:#000000">proceedingJoinPoint</span>.<span style="color:#000000">proceed</span>();
<span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"环绕之后........."</span>);
}
}</span></span>
切点统一抽取:把相同的切点抽取出来,相当于是一个方法,减少了繁琐的重复书写。
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Pointcut</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(* com.atguigu.spring5.aopanno.User.add(..))"</span>) <span style="color:#aa5500">// 抽取切点</span>
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#0000ff">pointdemo</span>() {
}
<span style="color:#aa5500">// 使用统一切点</span>
<span style="color:#555555">@Before</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"pointdemo()"</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#0000ff">before</span>() {
<span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"before........."</span>);
}</span></span>
3、事务
-
声明式事务注解,
SpringBoot
项目中只需要使用@Transactional
注解即可,不需要其它xml文件配置;
<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Transactional</span>(<span style="color:#000000">propagation</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Propagation</span>.<span style="color:#000000">REQUIRED</span>,<span style="color:#000000">isolation</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Isolation</span>.<span style="color:#000000">READ_COMMITTED</span>,<span style="color:#000000">readOnly</span> <span style="color:#981a1a">=</span> <span style="color:#221199">true</span>,<span style="color:#000000">rollbackFor</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Exception</span>.<span style="color:#770088">class</span>,<span style="color:#000000">timeout</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1</span>,<span style="color:#000000">noRollbackFor</span> <span style="color:#981a1a">=</span> <span style="color:#000000">UncheckedIOException</span>.<span style="color:#770088">class</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#0000ff">method1</span>() {
<span style="color:#aa5500">// ...</span>
}</span></span>
-
propagation
事务传播机制:-
REQUIRED:默认值,如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务;
-
REQUIRES_NEW:首先创建一个新的事务,如果当前存在事务,则把当前事务挂起;
-
SUPPORTS 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行;
-
NOT_SUPPORTED 以非事务方式运行,如果当前存在事务,则把当前事务挂起;
-
NEVER 以非事务方式运行,如果当前存在事务,则抛出异常;
-
MANDATORY 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常;
-
NESTED 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行; 如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
-
-
isolation
隔离级别:-
DEFAULT 使用后端数据库默认的隔离级别
-
READ_UNCOMMITTED 读取未提交数据(会出现脏读, 不可重复读)
-
READ_COMMITTED 读取已提交数据(会出现不可重复读和幻读)
-
REPEATABLE_READ 可重复读(会出现幻读)
-
SERIALIZABLE 串行化
-
-
timeout
:超时时间-
事务需要在一定时间内进行提交,如果不提交进行回滚
-
默认值是 -1 ,即不设置超时时间,单位是秒 s
-
-
readonly:是否只读
-
值为 true 表示查询,不能修改
-
值为 false 表示可查询可写
-
-
rollbackFor:回滚哪些异常
-
设置出现哪些异常时进行事务回滚,默认出现运行时异常时都回滚
-
-
noRollbackFor:设置出现哪些异常时不进行事务回滚
-
默认检查时异常都不进行回滚。
-
4、单元测试
-
引入测试依赖:
<span style="background-color:#f8f8f8"><span style="color:#981a1a"><</span><span style="color:#000000">dependency</span><span style="color:#981a1a">></span> <span style="color:#981a1a"><</span><span style="color:#000000">groupId</span><span style="color:#981a1a">></span><span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">boot</span><span style="color:#981a1a"></</span><span style="color:#000000">groupId</span><span style="color:#981a1a">></span> <span style="color:#981a1a"><</span><span style="color:#000000">artifactId</span><span style="color:#981a1a">></span><span style="color:#000000">spring</span><span style="color:#981a1a">-</span><span style="color:#000000">boot</span><span style="color:#981a1a">-</span><span style="color:#000000">starter</span><span style="color:#981a1a">-</span><span style="color:#000000">test</span><span style="color:#981a1a"></</span><span style="color:#000000">artifactId</span><span style="color:#981a1a">></span> <span style="color:#981a1a"><</span><span style="color:#000000">scope</span><span style="color:#981a1a">></span><span style="color:#000000">test</span><span style="color:#981a1a"></</span><span style="color:#000000">scope</span><span style="color:#981a1a">></span> <span style="color:#981a1a"></</span><span style="color:#000000">dependency</span><span style="color:#981a1a">></span></span>
-
直接开始单元测试:
<span style="background-color:#f8f8f8"><span style="color:#555555">@SpringBootTest</span>(<span style="color:#000000">classes</span> <span style="color:#981a1a">=</span> <span style="color:#000000">JunitApplication</span>.<span style="color:#770088">class</span>) <span style="color:#aa5500">// classes属性可选,用于指定测试单元所加载的配置类,默认就是SpringBoot的引导类</span> <span style="color:#770088">class</span> <span style="color:#0000ff">Springboot04JunitApplicationTests</span> { <span style="color:#aa5500">//注入你要测试的对象</span> <span style="color:#555555">@Autowired</span> <span style="color:#770088">private</span> <span style="color:#000000">BookDao</span> <span style="color:#000000">bookDao</span>; <span style="color:#555555">@Test</span> <span style="color:#aa5500">// 具体的测试方法</span> <span style="color:#008855">void</span> <span style="color:#000000">contextLoads</span>() { <span style="color:#aa5500">//执行要测试的对象对应的方法</span> <span style="color:#000000">bookDao</span>.<span style="color:#000000">save</span>(); <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"two..."</span>); } }</span>
2、Mabatis
1、基本使用
-
导入依赖:
<span style="background-color:#f8f8f8"><span style="color:#117700"><</span><span style="color:#117700">dependencies</span><span style="color:#117700">></span> <span style="color:#aa5500"><!--1.导入对应的starter--></span> <span style="color:#117700"><</span><span style="color:#117700">dependency</span><span style="color:#117700">></span> <span style="color:#117700"><</span><span style="color:#117700">groupId</span><span style="color:#117700">></span>org.mybatis.spring.boot<span style="color:#117700"></</span><span style="color:#117700">groupId</span><span style="color:#117700">></span> <span style="color:#117700"><</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span>mybatis-spring-boot-starter<span style="color:#117700"></</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span> <span style="color:#117700"><</span><span style="color:#117700">version</span><span style="color:#117700">></span>2.2.0<span style="color:#117700"></</span><span style="color:#117700">version</span><span style="color:#117700">></span> <span style="color:#117700"></</span><span style="color:#117700">dependency</span><span style="color:#117700">></span> <span style="color:#117700"><</span><span style="color:#117700">dependency</span><span style="color:#117700">></span> <span style="color:#117700"><</span><span style="color:#117700">groupId</span><span style="color:#117700">></span>mysql<span style="color:#117700"></</span><span style="color:#117700">groupId</span><span style="color:#117700">></span> <span style="color:#117700"><</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span>mysql-connector-java<span style="color:#117700"></</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span> <span style="color:#117700"><</span><span style="color:#117700">scope</span><span style="color:#117700">></span>runtime<span style="color:#117700"></</span><span style="color:#117700">scope</span><span style="color:#117700">></span> <span style="color:#117700"></</span><span style="color:#117700">dependency</span><span style="color:#117700">></span> <span style="color:#117700"></</span><span style="color:#117700">dependencies</span><span style="color:#117700">></span></span>
-
配置数据源:
<span style="background-color:#f8f8f8"><span style="color:#aa5500">#2.配置相关信息</span> <span style="color:#0000ff">spring</span>: <span style="color:#0000ff"> datasource</span>: <span style="color:#0000ff"> driver-class-name</span>:<span style="color:#009900"> com.mysql.cj.jdbc.Driver</span> <span style="color:#0000ff"> url</span>:<span style="color:#009900"> jdbc</span>:<span style="color:#009900">mysql</span>:<span style="color:#009900">//localhost</span>:<span style="color:#009900">3306/ssm_db</span> <span style="color:#0000ff"> username</span>:<span style="color:#009900"> root</span> <span style="color:#0000ff"> password</span>:<span style="color:#009900"> root</span> <span style="color:#0000ff">mybatis</span>: <span style="color:#aa5500"> # mapper接口在java目录下,对应的xml文件在resources目录下,如果它俩的路径名称不一致,则需要如下配置来指明mapper接口对应的xml文件的位置。</span> <span style="color:#0000ff"> mapper-locations</span>:<span style="color:#009900"> classpath</span>:<span style="color:#009900">mapper/*.xml </span> <span style="color:#aa5500"> # 指定实体类所在包路径来让mybatis自动扫描到自定义的实体类</span> <span style="color:#0000ff"> type-aliases-package</span>:<span style="color:#009900"> com.chf.pojo </span> <span style="color:#aa5500"> # 输出日志</span> <span style="color:#0000ff"> configuration</span>: <span style="color:#0000ff"> log-impl</span>:<span style="color:#009900"> org.apache.ibatis.logging.stdout.StdOutImpl </span> <span style="color:#aa5500"> #开启驼峰自动映射。前提是Java属性名和数据库表的字段都遵循命名规范:Java首字母小写,后面每个单词首字母大写,驼峰;SQL命名规范:全部小写,单词之间采用下划线分割。一个单词的就不必用驼峰或者下划线了</span> <span style="color:#0000ff"> map-underscore-to-camel-case</span>:<span style="color:#009900"> true</span></span>
-
实体类:
<span style="background-color:#f8f8f8">// lombok注解。。。 public class Book { // 默认情况下字段名和属性名相同的进行匹配 private Integer id; private String carNum; private String brand; private Double guidePrice; private String produceTime; private String carType; }</span>
-
映射接口(mapper):
<span style="background-color:#f8f8f8">@Mapper // 声明这是mapper接口,同时也将其实现类对象加载到容器中 public interface CarMapper {、 /*@Select("select * from tbl_book where id = #{id}") // 简单SQL语句可以在这里直接写。@Delete、@Insert、@Update。 public Book getById(Integer id);*/ /** * 插入汽车 * @return * @param car */ int insert(Car car); // 传入参数是实体类 int insert2(Map map); // 传入参数是map集合 /** * 按id删除车辆信息 * @param id * @return */ int delete(Long id); /** * 更新车辆信息 * @param car * @return */ int update(Car car); }</span>
-
xml
文件:<span style="background-color:#f8f8f8"><!--namespace值等于mapper接口路径--> <mapper namespace="com.chf.mapper.CarMapper"> <insert id="insert"> <!--id标签值与对应的mapper接口中的方法名相同--> insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) <!--#{}接收的参数是所传入对象的属性名称--> values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType}) </insert> <insert id="insert2"> <insert id="insertStudentByMap" parameterType="map"><!--指定传入参数是map集合--> insert into t_student values (null,#{姓名},#{年龄},#{身高},#{生日},#{性别})<!--#{}里的是map的key,实际插入的是map的value--> </insert> </insert> <!--如果占位符只有一个,其实可以随便写里面的内容但不能不写,但最好见名知意,这次只是测试--> <delete id="delete"> delete from t_car where id = #{dasdad} </delete> <update id="update"> update t_car set <!--同理,#{}所接收参数是所传入实体类的属性名称--> car_num=#{carNum}, brand=#{brand}, guide_price=#{guidePrice}, produce_time=#{produceTime}, car_type=#{carType} where id=#{id} </update> </mapper></span>
-
在需要的地方注入该
mapper
,然后调用其中方法即可。
2、常用查询
-
主要解释
mapper
接口文件和xml
文件。 -
mapper
接口:<span style="background-color:#f8f8f8">@Mapper // 声明这是mapper接口,同时也将其实现类对象加载到容器中 public interface CarMapper { // 查询全部。并按时间排序 List<Car> selectAllByAscOrDesc(String str); // 模糊查询 List<Car> selectByBrandLike(String str); // 查询单个对象,返回map集合。集合key是查询的字段名,value是实际值 Map<String,Object> selectByIdRetMap(Long id); // 查询多个对象,返回多个map,存放到List集合中 List<Map<String,Object>> selectAllRetListMap(); // 指定外层map的key是查询到的哪一个字段值。 @MapKey("id") Map<Long,Map<String,Object>> selectAllRetMap(); // 多参数:@Param("xxx")里的值和select标签中参数对应即可。 List<Student> selectByNameAndSex(@Param("nnn") String name, @Param("sss") Character sex); // 聚合查询,返回基本数据类型 Long selectTotal(); }</span>
-
xml
文件:查询标签比其它标签多了resultType
属性,属性值是返回值类型。<span style="background-color:#f8f8f8"><!--namespace值等于mapper接口路径--> <mapper namespace="com.chf.mapper.CarMapper"> <!--简单查询--> <select id="selectAllByAscOrDesc" resultType="Car"><!--返回实体类对象,可用集合接收--> select id, car_num carNum,<!--实体类属性名与表字段名不对应的解决办法之二:为查询字段起别名--> brand, guide_price guidePrice, produce_time produceTime, car_type carType from t_car order by produce_time ${ascOrDesc} </select> <!--模糊查询。--> <select id="selectByBrandLike" resultType="Car"> select id, car_num carNum, brand, guide_price guidePrice, produce_time produceTime, car_type carType from t_car where brand like "%"#{brand}"%" </select> <!--查询单个对象,返回map集合--> <select id="selectByIdRetMap" resultType="map"> select id, car_num carNum, brand, guide_price guidePrice, produce_time produceTime, car_type carType from t_car where id = #{id} </select> <!--查询多个对象,返回多个map,存放到List集合中。注意返回值不是List!--> <select id="selectAllRetListMap" resultType="map"> select id, car_num carNum, brand, guide_price guidePrice, produce_time produceTime, car_type carType from t_car </select> <!--查询多个对象,返回多个map,存放到外层map集合中。--> <select id="selectAllRetMap" resultType="map"> select id, car_num carNum, brand, guide_price guidePrice, produce_time produceTime, car_type carType from t_car </select> <!--查询多个对象,多参数查询--> <select id="selectByNameAndSex" resultType="Car"> select * from t_car where name = #{nnn} and sex = #{sss} </select> <!--返回值是基本数据类型--> <select id="selectTotal" resultType="long"> select count(*) from t_car </select> </mapper></span>
3、动态SQL
1、where - if 标签
<span style="background-color:#f8f8f8"><span style="color:#333333">@Mapper
public interface CarMapper {
/**
* 多条件查询
*/
List<Car> selectByMultiCondition(@Param("brand") String brand,
@Param("guidePrice") Double guidePrice,
@Param("carType") String carType);
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333"><mapper namespace="com.chf.mapper.CarMapper">
<!--
1、如果f标签中test属性的值为true,则if标签中的sql语句就会拼接。反之就不会拼接
2、test属性中可以使用的是:
当使用了@Param注解,那么test中要出现的是@Param注解指定的参数名。
当没有使用@Param注解,那么test中要出现的是:param1 param2 param3 ...
当使用了POJO,那么test中出现的是POJO类的属性名
3、在MyBatis的动态SQL中,不能使用&&,使用的是and
4、标签内与#{}内写的都是POJO属性名,其余是SQL的字段名
5、刚开始的1 = 1是防止后面出现空传值导致SQL语句出现错误
-->
<select id="selectByMultiCondition" resultType="Car">
select
id,car_num,brand,guide_price,produce_time,car_type
from
t_car
where
1 = 1
<if test="brand != null and brand != ''">
and brand like "%"#{brand}"%"
</if>
<if test="guidePrice != null and guidePrice != ''">
and guide_price >= #{guidePrice}
</if>
<if test="carType != null and carType != ''">
and car_type like "%"#{carType}"%"
</if>
</select>
<!--包含where标签时。if并不是只能用在where语句中!-->
<!--
where标签是专门负责where子句动态生成的
这里将1 = 1去掉了并且第一个if标签语句还有"and"关键字,但where标签会自动去除多余的and或or
所有条件都有空时,where标签保证不会生成where子句
-->
<select id="selectByMultiConditionWithWhere" resultType="Car">
select
id,car_num,brand,guide_price,produce_time,car_type
from
t_car
<where>
<if test="brand != null and brand != ''">
and brand like "%"#{brand}"%"
</if>
<if test="guidePrice != null and guidePrice != ''">
and guide_price >= #{guidePrice}
</if>
<if test="carType != null and carType != ''">
and car_type like "%"#{carType}"%"
</if>
</where>
</select>
</mapper></span></span>
2、trim
-
增删前后缀
<span style="background-color:#f8f8f8"><span style="color:#333333">@Mapper
public interface CarMapper {
/**
* 使用trim标签
*/
List<Car> selectByMultiConditionWithTrim(@Param("brand") String brand,
@Param("guidePrice") Double guidePrice,
@Param("carType") String carType);
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333"><mapper namespace="com.chf.mapper.CarMapper">
<!--
prefix:加前缀
suffix:加后缀
prefixOverrides:删除前缀
suffixOverrides:删除后缀
以下表示在trim标签所有内容的前面添加where,后缀的and或者or去掉
-->
<select id="selectByMultiConditionWithTrim" resultType="Car">
select
id,car_num,brand,guide_price,produce_time,car_type
from
t_car
<trim prefix="where" suffixOverrides="and|or">
<if test="brand != null and brand != ''">
brand like "%"#{brand}"%" and
</if>
<if test="guidePrice != null and guidePrice != ''">
guide_price >= #{guidePrice} and
</if>
<if test="carType != null and carType != ''">
car_type like "%"#{carType}"%"
</if>
</trim>
</select>
</mapper></span></span>
3、set 标签
-
主要使用在update语句当中,用于生成set关键字,同时去掉最后多余的",";
-
比如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。
<span style="background-color:#f8f8f8"><span style="color:#333333">@Mapper
public interface CarMapper {
/**
* 使用set标签进行更新
*/
int updateBySet(Car car);
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333"><mapper namespace="com.chf.mapper.CarMapper">
<update id="updateBySet">
update
t_car
<set>
<if test="carNum != null and carNum != ''">car_num = #{carNum},</if>
<if test="brand != null and brand != ''">brand = #{brand},</if>
<if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if>
<if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if>
<if test="carType != null and carType != ''">car_type = #{carType}</if>
</set>
where
id = #{id}
</update>
</mapper></span></span>
4、choose where otherwise
-
三个标签一起使用,相当于
if-else if-else
<span style="background-color:#f8f8f8">@Mapper public interface CarMapper { /** * 使用choose when otherwise标签 */ List<Car> selectByChoose(@Param("brand") String brand, @Param("guidePrice") Double guidePrice, @Param("carType") String carType); }</span>
<span style="background-color:#f8f8f8"><mapper namespace="com.chf.mapper.CarMapper"> <select id="selectByChoose" resultType="Car"> select id,car_num,brand,guide_price,produce_time,car_type from t_car <where> <choose> <when test="brand != null and brand != ''"> brand like "%"#{brand}"%" </when> <when test="guidePrice != null and guidePrice != ''"> guide_price >= #{guidePrice} </when> <otherwise> car_type like "%"#{carType}"%" </otherwise> </choose> </where> </select> </mapper></span>
5、foreach标签
-
常用于批量删除,
in
关键字查询:<span style="background-color:#f8f8f8">@Mapper public interface CarMapper { /** * 根据id批量删除 foreach */ int deleteByIds(@Param("ids") Long[] ids); }</span>
<span style="background-color:#f8f8f8"><mapper namespace="com.chf.mapper.CarMapper"> <!-- foreach标签的属性: collection:所传入的数组或集合参数 item:经过处理后的数组或集合中的元素,并可赋值给#{} separator:各个元素之间的分隔符 open:在所有元素之前添加的开始符号 close:在所有元素之后添加的结束符号 --> <update id="deleteByIds"> delete from t_car where id in <foreach collection="ids" item="aaa" separator="," open="(" close=")"> #{aaa} </foreach> </update> </mapper></span>
4、分页
-
可以直接在SQL语句中为
limit
关键字传入参数。startIndex(起始下标,下标从0开始)和pageSize(每页显示的记录条数)。 -
使用分页插件对查询到的分页结果进行包装:
-
引入
PageHelper
插件依赖:<span style="background-color:#f8f8f8"><dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.12</version> </dependency></span>
-
在核心启动类的@SpringBootApplication注解后面添加:
<span style="background-color:#f8f8f8">@SpringBootApplication(exclude = PageHelperAutoConfiguration.class)</span>
-
在代码中使用:
<span style="background-color:#f8f8f8">public PageInfo<Car> testPageInfo(int pageNum,int pageSize) { int startIndex = (pageNum - 1) * pageSize; List<Car> cars = carMapper.selectByPage(startIndex,pageSize); // 封装查询后的结果 PageInfo<Car> carPageInfo = new PageInfo<>(car,pageSize); return carPageInfo; }</span>
-
3、mybatis-plus
1、基本使用
-
调用
mapper
的基本方法,在serviceImpl
类中使用LambdaQueryWrapper
和LambdaUpdateWrapper
构造查询条件,查询或修改时把条件语句作为参数传递进去即可。
<span style="background-color:#f8f8f8"><span style="color:#333333">public interface UserMapper extends BaseMapper<User> { // BaseMapper是MyBatis-Plus提供的模板mapper,其中包含了基本的CRUD方法,泛型为操作的实体类型
}</span></span>
MyBatis-Plus
中有一个接口IService和
其实现类ServiceImpl
,封装了常见的业务层逻辑:
<span style="background-color:#f8f8f8"><span style="color:#333333">public interface UserService extends IService<User> {
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">/**
* ServiceImpl实现了IService,提供了IService中基础功能的实现
* 若ServiceImpl无法满足业务需求,则可以使用自定的UserService定义方法,并在实现类中实现
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//避免使用字符串表示字段,防止运行时错误
queryWrapper
.like(StringUtils.isNotBlank(username), User::getName, username)
.ge(ageBegin != null, User::getAge, ageBegin)
.le(ageEnd != null, User::getAge, ageEnd);
List<User> users = userMapper.selectList(queryWrapper);
}</span></span>
分页查询:
-
配置分页插件:
<span style="background-color:#f8f8f8"><span style="color:#333333">@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper") //可以将主类中的注解移到此处
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new
PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}</span></span>
-
使用:
<span style="background-color:#f8f8f8"><span style="color:#333333">@Test
public void testPage(){
//设置分页参数
Page<User> page = new Page<>(1, 5);
userMapper.selectPage(page, null);
//获取分页数据
List<User> list = page.getRecords();
list.forEach(System.out::println);
System.out.println("当前页:"+page.getCurrent());
System.out.println("每页显示的条数:"+page.getSize());
System.out.println("总记录数:"+page.getTotal());
System.out.println("总页数:"+page.getPages());
System.out.println("是否有上一页:"+page.hasPrevious());
System.out.println("是否有下一页:"+page.hasNext());
}</span></span>
2、常用注解
-
@TableName("t_user")
:在实体类上添加该注解,用以标识该实体类所对应的表名字,默认为实体类首字母小写。开发过程中,数据库中对应的表通常都有t_
或tb\_
前缀,我们可以在配置文件中统一配置全局前缀,@TableName("t_user")
注解中就不用写t_
了;mybatis-plus.global-config.db-config.table-prefix
; -
@TableId(value = "xxx")
:指定表主键 id,未指定的话默认将id
属性作为主键。其value值指的是数据库表中的主键字段,默认是id
; -
@TableField("xxx")
:指定该实体类属性与表中哪个字段对应,默认和属性名同名或驼峰法转下划线法; -
@TableLogic
:作用于某个属性,把它作为逻辑删除属性; -
条件构造的
QueryWrapper
和LambdaQueryWrapper
; -
分页查询:
Page page = new Page<>(1, 5);
;
3、MyBatis中的$和#有什么区别?
-
使用#设置参数时,MyBatis会创建预编译的SQL语句,然后在执行SQL时MyBatis会为预编译SQL中的占位符(?)赋值。预编译的SQL语句执行效率高,并且可以防止注入攻击;
-
使用$设置参数时,MyBatis只是创建普通的SQL语句,然后在执行SQL语句时MyBatis将参数直接拼入到SQL里。这种方式在效率、安全性上均不如前者,但是可以解决一些特殊情况下的问题;
-
在一些动态表格(根据不同的条件产生不同的动态列)中,我们要传递SQL的列名,根据某些列进行排序,或者传递列名给SQL都是比较常见的场景,这就无法使用预编译的方式了(因为这时的SQL语句都不完整,无法预编译);
@Mapper与@MapperScan
区别与联系:
-
@Mapper用在接口上,在编译之后会生成相应的接口实现类,并放入 IOC 容器。@MapperScan 在SpringBootApplication启动类上面使用,如下,说明扫描“cn.cvs.mapper”此包下的所有mapper接口,生成对应的实现类;
-
@Mapper是队单个接口类的注解,单个操作。(接口少的时候适合使用),而@MapperScan是对整个包之下的所有的接口类的注解,是批量的操作。使用@MapperScan之后,接口类就不需要再使用@Mapper注解了;
-
@MapperScan可以扫描多个包,参数传一个字符串数组即可。
<span style="background-color:#f8f8f8"><span style="color:#333333">@Mapper // 用在接口上,在编译之后会生成相应的接口实现类
public interface ItripUserMapper {
public ItripUser getItripUserById(@Param(value = "id") Long id)throws Exception;
public List<ItripUser> getItripUserListByMap(Map<String,Object> param)throws Exception;
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">@MapperScan("cn.cvs.mapper") // 扫描指定包下所有的接口类,然后所有接口在编译之后都会生成相应的实现类
@SpringBootApplication
public class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
}</span></span>
3、Spring MVC
1、请求方法注解
-
@RequestMapping(value = {"/testRequestMapping", "/test"}
:配置请求映射路径,通常是作用于controller类上,用于标识和区别某一类的请求类型,value值可以有多个,请求匹配任意一个即可。支持ant风格的路径:-
?:表示任意的单个字符;
-
:表示任意的0个或多个字符;
-
*:表示任意的一层或多层目录,注意:在使用**时,只能使用/**/xxx的方式。
-
-
注解参数详解:
-
value;
-
method;
-
params:通过请求的请求参数匹配请求映射,属性值是一个字符串类型的数组,可以通过四种表达式设置请求参数和请求映射的匹配关系:
-
"param":要求请求映射所匹配的请求必须携带param请求参数
-
"!param":要求请求映射所匹配的请求必须不能携带param请求参数
-
"param=value":要求请求映射所匹配的请求必须携带param请求参数且param=value
-
"param!=value":要求请求映射所匹配的请求必须携带param请求参数但是param!=value
-
-
<span style="background-color:#f8f8f8"><span style="color:#333333">@RequestMapping(
value = {"/testRequestMapping", "/test"} // 指定路径
,method = {RequestMethod.GET, RequestMethod.POST} // 指定请求方法类型
,params = {"username","password!=123456"}
)
public String testRequestMapping(){
return "success";
}</span></span>
-
@GetMapping("/get")
:接收get请求,支持ant风格路径,支持路径传参,例下:id和username是接收请求路径中的参数,,且在方法参数中使用@PathVariable("id")
接收参数。<span style="background-color:#f8f8f8">@RequestMapping("/testRest/{id}/{username}") public String testRest(@PathVariable("id") String id, @PathVariable("username") String username){}</span>
-
@PostMapping("/post1")
:接收post请求(其余和前述一样); -
@DeleteMapping("/delete1")
:接收delete请求(其余和前述一样); -
@UpdateMapping("/update1")
:接收update请求(其余和前述一样);
2、请求方法参数注解
-
@PathVariable:获取请求路径中传递的参数;
-
@RequestParam:基本不用,因为它不是REST风格;
-
@RequestBody:获取请求体参数,是JSON格式的,当前请求的请求体就会为当前注解所标识的形参赋值,如下:注意该参数也可以是一个实体类,对象,只要传递的请求体参数与该实体类的部分属性的变量名有对应即可。
<span style="background-color:#f8f8f8">@PostMapping("/testRequestBody") public String testRequestBody(@RequestBody String requestBody){ /**/ }</span>
-
@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器;
-
@RestController注解是@Controller和@ResponseBody的一个复合注解;
3、统一异常处理
-
@ControllerAdvice将当前类标识为异常处理的组件。例如:
<span style="background-color:#f8f8f8">@ControllerAdvice // mvc统一异常处理! public class ExceptionController { //@ExceptionHandler用于设置所标识方法处理的异常 @ExceptionHandler(ArithmeticException.class) //ex表示当前请求处理中出现的异常对象 public String handleArithmeticException(Exception ex, Model model){ model.addAttribute("ex", ex); return "error"; } }</span>
4、过滤器/拦截器
5、文件上传与下载
文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"
SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息
上传步骤:
a>添加依赖:
<span style="background-color:#f8f8f8"><span style="color:#333333"><!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency></span></span>
b>在SpringMVC的配置文件中添加配置:
<span style="background-color:#f8f8f8"><span style="color:#333333"><!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean></span></span>
c>控制器方法:
<span style="background-color:#f8f8f8"><span style="color:#333333">@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//处理文件重名问题
String hzName = fileName.substring(fileName.lastIndexOf("."));
fileName = UUID.randomUUID().toString() + hzName;
//获取服务器中photo目录的路径
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
if(!file.exists()){
file.mkdir();
}
String finalPath = photoPath + File.separator + fileName;
//实现上传功能
photo.transferTo(new File(finalPath));
return "success";
}</span></span>
4、Spring Boot
1、基本认识
parent:
开发Spring Boot程序都要继承一个 spring-boot-starter-parent,其中定义了上百个依赖管理。我们添加依赖的时候如果不指定版本号,默认就是继承parent 定义的版本,好处是它里边定义的一组版本之间不会产生依赖冲突,省了我们很多的麻烦;
starter:
开发者要完成某一项功能时,需要引入一大堆依赖,容易出错,starter则是定义这样一组固定技术搭配,完成某项功能时,只要引入固定starter
即可,而不必写若干个依赖了。要注意它与parent的区别;
starter命名规范
starter所属 | 命名规则 | 示例 |
---|---|---|
官方提供 | spring-boot-starter-技术名称 | spring-boot-starter-web spring-boot-starter-test |
第三方提供 | 第三方技术名称-spring-boot-starter | mybatis-spring-boot-starter druid-spring-boot-starter |
引导类:
Spring Boot 使用@SpringBootApplication
注解标注了一个类,该类的main
方法就是程序启动的入口,成为引导类。
内嵌tomcat:
内嵌Tomcat服务器是 Spring Boot 辅助功能之一。内嵌 Tomcat 工作原理是将 Tomcat 服务器作为对象运行,并将该对象交给Spring容器管理。
2、Spring Boot中的配置文件
配置文件优先级:
properties(最高)> yml > yaml(最低),不同配置文件中相同配置按照加载优先级相互覆盖,不同配置则全部保留。
读取配置文件:
读取单一数据:
yaml中保存的单个数据,可以使用Spring中的注解@Value读取单个数据,属性名引用方式:${一级属性名.二级属性名……}
读取全部数据:
读取单一数据可以解决读取数据的问题,但是如果定义的数据量过大,这么一个一个书写肯定会累死人的,SpringBoot提供了一个对象,能够把所有的数据都封装到这一个对象中,这个对象叫做Environment,使用自动装配注解可以将所有的yaml数据封装到这个对象中
数据封装到了Environment对象中,获取属性时,通过Environment的接口操作进行,具体方法是getProperties(String),参数填写属性名即可
读取对象数据:使用@ConfigurationProperties必须告诉他加载的数据前缀是什么,记得数据属性名要与对象的变量名一一对应
3、热部署
热部署,简单来说就是程序修改后,服务器会自动把更新后的程序给重新加载一遍,而不用重启项目。
使用热部署:
步骤①:导入开发者工具对应的坐标
<span style="background-color:#f8f8f8"><span style="color:#333333"><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency></span></span>
步骤②:修改项目后,使用快捷键完成热部署:Build --- Build Project;
开启自动热部署:
自动热部署是和开发工具有关的,就是允许了开发工具的自动进行热部署,以下以idea为例设置idea中启动热部署。
步骤①:设置允许自动构建项目
打开【File】,选择【settings...】,在面板左侧的菜单中找到【Compile】选项,然后勾选【Build project automatically】,意思是自动构建项目
步骤②:允许在程序运行时进行自动构建
使用快捷键【Ctrl】+【Alt】+【Shit】+【/】打开维护面板,选择第1项【Registry...】
在选项中搜索comple
,然后勾选compiler.automake.allow.when.app.running
项即可。
idea
中默认当idea
工具失去焦点5秒后进行热部署。其实就是你从idea工具中切换到其他工具时进行热部署,比如改完程序需要到浏览器上去调试,这个时候idea就自动进行热部署操作。
4、SpringBoot解析yml中的数字
-
做SpringBoot项目的时候,要连接本地数据库作为,当时把数据库密码设置成自己的生日,以0开头的四位数,但是启动项目时总是报错数据库密码错误;
-
检查了几遍数据库密码都没有问题,也上网找了很多解决方案,有说数据库加密方式和SpringBoot连接数据库时加密方式不一致的,等等;
-
最后,我在测试类中直接读取密码,结果看到取出来的数字不是在yml文件中配置的值,然后上网一查才知道原来是SpringBoot会默认把0开头的数字看成是八进制的,0x开头的就看成是十六进制,所以才会密码错误;
-
最后我就把密码改了,不以0开头,解决;