说明:SpringBoot一天速成不是口号,而在于您的基础。
1.此演示目的就是为了让大家速成。口号:“快快快狠”。
2.具备半年以上"SSM框架+Maven"实战经验的开发人员
3.跟着此系列博文《SpringBoot一天速成》练习一遍
4.这套演练包括工程的:持久层、服务层、web层,采用Intellej idea工具。
5.所有源码和资料免费提供给读者,需要的留言。
6.笔者将实践过程中遇到的问题与大家分享,让大家少走弯路。(请阅读注释部分)

SpringBoot是干嘛的?"简化开发,独立运行",瞄准的目标:微服务。下面是官方原话:
	  Spring Boot makes it easy to create stand-alone, production-grade Spring based 
Applications that you can "just run". We take an opinionated view of 
the Spring platform and third-party libraries so you can get started with minimum fuss. 
Most Spring Boot applications need very little Spring configuration.

====>>> 持久层–>服务层 演练开始……
采用****的方式来演示《SpringBoot一天速成演练》,先从数据库开始最后到web层
声明:@author:拈花为何不一笑,“这是一套演练对于细节方面,需要读者自己完善。”

 1.准备Intellij idea工具(此工具集成了Spring Initializr比eclipse更高效,缺点是占用大量内存接近900M)
		1.1 下载ideaIU-2018.2.6.exe
		1.2 **方法(此工具是收费的,若果是学习用可以使用**版,企业用建议购买)
		这些资源,有需要的笔者都可以提供,请留言。

第1集 SpringBoot一天速成 (SpringBoot)

 2.Intellij Idea工具中创建工程
	File菜单--> New -->Project-->弹出对话框:选择Spring Initializr(用来初始化构建工程的环境),
	接下来的操作看图,更清楚,如下:

第1集 SpringBoot一天速成 (SpringBoot)

第1集 SpringBoot一天速成 (SpringBoot)

第1集 SpringBoot一天速成 (SpringBoot)

第1集 SpringBoot一天速成 (SpringBoot)

 3.在Mysql(版本:MySQL-5.5.61)中创建数据库和建表等
	sql脚本:createTable.sql,有需要的笔者可以分享出来...
	3.1 数据库名称;testsb2mybatis
	3.2 表两张:dept和emp
			截一张表结构图,如下:

|第1集 SpringBoot一天速成 (SpringBoot)

4.编写Mapper接口和相关配置文件
	4.1.在resources目录下创建以下目录结构,如图:

第1集 SpringBoot一天速成 (SpringBoot)

	4.2.创建mybatis配置文件mybatis.xml和EmpMapper.xml文件(注意存放位置)

====>>> mybatis.xml

<?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>
    <!-- mybatis中加载的数据源datasource,由于与springboot进行整合,那么数据源交由Spring来管理,则配置在application.properties文件中了-->

    <!-- 配置 mybatis sql日志输出 STDOUT_LOGGING
        <settings>
            <setting name="logImpl" value="SLF4J" />
        </settings>
    -->
</configuration>

====>>> EmpMapper.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包中的相应的接口,这是Mybatis-Mapper方式的规则之一 -->
<mapper namespace="org.it.springboot4.mapper.EmpMapper">

<sql id="empfields">
    empno,ename,job,mgr,hiredate,sal,comm,deptno
</sql>

<!-- id与mapper接口方法名相同,resultType与mapper接口的方法的返回类型相同,这是Mybatis-Mapper方式的规则之二 -->
<!-- parameterType相当于itatis中的parameterClass,
	若参数为基本数据类型,占位符(#{参数名})可以是任意参数名;
	若参数为java对象,如User那么占位符中的参数名,取名要与User中的属性对应,因为通过getXXX从User中取值的 -->
<select id="findEmpById"  parameterType="java.lang.Integer" resultType="org.it.springboot4.entity.Emp">
    select
      <include refid="empfields"/>
     from emp where empno = #{拈花为何不一笑}
</select>

<!-- 模糊查询拼接符 '%${}%',基本数据类型的模糊查询拼接符只能使用'%${value}%',
	            不能这样'%${username}%',防止拼接注入'%${username}% or 1=1' -->

<!-- 查询研发部所有薪资大于或等于6600的员工,返回类型resultType直接映射成Map
    注意返回类型不是resultMap。
    1.resultType表示基本数据类型和包装类及自定义类,还有这里的java.util.Map接口下的实现类,
    若在此处误用resultMap是会因Map无法映射,而抛出异常:
        java.lang.IllegalArgumentException: Result Maps collection does not contain value for java.util.Map
    2.默认使用的是HashMap来实现Map,采用的是hash值对键进行排序,映射的数据顺序就有点乱,
        可以直接指定LinkedHashMap来排序按插入(sql查询字段的顺序)排序特性并去重复的字段(如这里的deptno,排在前面的保留)
    3.resultMap通常用于查询出多表关联数据与java类与类之间的关联关系进行映射,即通常所说的的一对多,多对多这类的映射关系。
-->
<select id="findEmpByDeptnoSal" parameterType="org.it.springboot4.entity.custom.EmpCustom" resultType="java.util.LinkedHashMap">
    SELECT
        e.empno,
        e.ename,
        e.hiredate,
        e.job,
        e.mgr,
        e.sal,
        e.deptno,
        e.comm,

        d.deptno,
        d.dname,
        d.location
    FROM emp e, dept d
    WHERE e.deptno = d.deptno
    <!-- mybatis动态sql,根据参数有无来动态添加查询条件,如果是Map作为查询条件的参数,则在if test中直接使用key名判断即可-->
   <if test="dname != null and dname !=''">
       AND d.dname = #{dname}
   </if>
    <if test="sal != null and sal !=''">
        AND sal &gt;= #{sal}
    </if>
</select>

<!-- 添加一个新员工,无需显示指明返回类型,mybatis自动把影响到的记录数据作为Integer返回 -->
<insert id="createEmp" parameterType="org.it.springboot4.entity.Emp" >
    insert  into emp(ename,hiredate,job,mgr,sal,comm,deptno)
    values (#{ename},#{hiredate},#{job},#{mgr},#{sal},#{comm},#{deptno})
</insert>

<!-- 创建并映射当前新增加的员工编号(返回的还是影响的记录数) -->
<!-- 通过mysql数据库提供的函数last_insert_id(),获取由数据库mysql自动生成的主键并映射到Emp的empno属性中 -->
<!-- 注意:1.返回的是一个整数不能是Emp对象 2.selectKey 中的order属性值必须大写AFTER 3.如果使用resultType会报一个坑人的异常提示:
	必须为元素类型 "insert" 声明属性 "resultType"。 -->
<insert id="createGetEmp"  parameterType="org.it.springboot4.entity.Emp">
    <selectKey keyColumn="empno" keyProperty="empno" order="AFTER" resultType="java.lang.Integer">
        SELECT LAST_INSERT_ID()
    </selectKey>
    insert  into emp(ename,hiredate,job,mgr,sal,comm,deptno)
    values (#{ename},#{hiredate},#{job},#{mgr},#{sal},#{comm},#{deptno})

</insert>

<!-- 删除员工,使用Map接收删除条件,其中currentEmpno为Map设置的键名 -->
<delete id="deleteEmp" parameterType="java.util.Map">
    delete from emp where empno = #{currentEmpno}
</delete>

<!-- 更新员工,这里使用if标签构建动态sql,防止空数据覆盖表中字段数据。其中set标签可以去最后面一个字段的逗号防止sql语法错误 -->
<update id="updateEmp" parameterType="org.it.springboot4.entity.Emp">
    update emp
    <set>
       <if test="ename != null and ename !=''">
            ename = #{ename},
        </if>

        <if test="hiredate != null and hiredate !=''">
             hiredate = #{hiredate},
        </if>

        <if test="job != null and job !=''">
            job = #{job},
        </if>
        <if test="mgr != null and mgr !=''">
            mgr = #{mgr},
        </if>
        <if test="sal != null and sal !=''" >
            sal = #{sal},
        </if>
        <if test="comm != null and comm !=''" >
            comm = #{comm},
        </if>
        <if test="deptno != null and deptno !=''" >
            deptno = #{deptno},
        </if>
    </set>
      where empno =#{empno}
        <if test="deptno != null and deptno !=''">
            and deptno = #{deptno}
        </if>
        <if test="mgr != null and mgr !=''">
            and mgr = #{mgr}
        </if>

</update>

</mapper>

继续…

4.3.创建实体类:Dept.java和Emp.java 及EmpCustom(扩展Emp,用于包装前端参数)

====>>> Dept .java

package org.it.springboot4.entity;
public class Dept {


private Integer deptno;

private String dname;

private String location;

public Dept() {//无参构造函数
}

public Integer getDeptno() {
    return deptno;
}

public void setDeptno(Integer deptno) {
    this.deptno = deptno;
}

public String getDname() {
    return dname;
}

public void setDname(String dname) {
    this.dname = dname;
}

public String getLocation() {
    return location;
}

public void setLocation(String location) {
    this.location = location;
}
}

====>>> Emp.java

package org.it.springboot4.entity;

import java.util.Date;


public class Emp {
private Integer empno;

private String ename;
private String job;
private Integer mgr;
private Date hiredate;
private Float sal;
private Float comm;

private Integer deptno;

public Emp() {
}

public Integer getEmpno() {
    return empno;
}

public void setEmpno(Integer empno) {
    this.empno = empno;
}

public String getEname() {
    return ename;
}

public void setEname(String ename) {
    this.ename = ename;
}

public String getJob() {
    return job;
}

public void setJob(String job) {
    this.job = job;
}

public Integer getMgr() {
    return mgr;
}

public void setMgr(Integer mgr) {
    this.mgr = mgr;
}

public Date getHiredate() {
    return hiredate;
}

public void setHiredate(Date hiredate) {
    this.hiredate = hiredate;
}

public Float getSal() {
    return sal;
}

public void setSal(Float sal) {
    this.sal = sal;
}

public Float getComm() {
    return comm;
}

public void setComm(Float comm) {
    this.comm = comm;
}

public Integer getDeptno() {
    return deptno;
}

public void setDeptno(Integer deptno) {
    this.deptno = deptno;
}
}

====>>> EmpCustom.java

package org.it.springboot4.entity.custom;

import org.it.springboot4.entity.Emp;

/**
 * 自定义Emp扩展类,用于Emp属性的扩展
 */
public class EmpCustom extends Emp {

    private String dname;

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }
}

继续…

	4.4.这里采用Mybatis-Mapper接口的开发方式,使用Mybatis。
	(还有一种方式是向下兼容itatis,推荐Mybatis-Mapper)
	  编写EmpMapper接口,这里有一定的规则,要与EmpMapper.xml中的配置相对应,里面有注释说明。

====>>> EmpMapper.java(看清楚了,这个后缀是java)

package org.it.springboot4.mapper;

import org.it.springboot4.entity.Emp;
import org.it.springboot4.entity.custom.EmpCustom;

import java.util.List;
import java.util.Map;

/**
 * mapper包相当于dao层包
 *  这里演示Mybatis-Mapper方式使用mybatis
 *      这个接口中的方法是需要遵守一定的规范的
 *  springboot自动扫描会扫描mapper包(未与sprngboot整合时,包的扫描是由mybatis来扫描的且mapper映射文件与java mapper接口放在同一个包中)
 */
public interface EmpMapper {

    //查询员工根据员工编号(按实际开发过程中,service层方法是要求抛出异常的,这里简单演示就省略了)
    Emp findEmpById(Integer empno);

    // 查询研发部所有薪资大于或等于6600的员工(也可以使用Map作为参数,mapper.xml中取参数值方式#{map设置的key名})
    List<Map> findEmpByDeptnoSal(EmpCustom empCustom);

    //增加一个员工并返回影响的记录数
    Integer createEmp(Emp emp);

    //创建并映射当前新增加的员工编号(返回的还是影响的记录数)
    Integer createGetEmp(Emp emp);

    //删除员工
    Integer deleteEmp(Map paramMap);

    //更新员工
    Integer updateEmp(Emp emp);
}

继续

	4.5.创建application.properties配置文件,springboot入口类启动时会加载此配置文件
		此配置在这里,笔者将其分成三块:a.基础配置信息 b.数据源配置 c.ybatis配置
	  配置文件内容,如下:

====>>> application.properties

##########基础配置信息 ##########
#debug=ture
#server.servlet.context-path=/myspringboot4
server.port=8080
spring.http.encoding.charset=UTF-8
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss SSS
spring.mvc.date-format=yyyy-MM-dd
#json缩进排版
spring.jackson.serialization.indent-output=true
##########数据源配置##########
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#这里有个时区问题,需要注意,GMT+8 ,其中%2B表示"+"
spring.datasource.url=jdbc:mysql://localhost:3306/testsb2mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
#spring.jpa.show-sql=true
######mybatis配置 ######
mybatis.config-location=classpath:/mybatis/mybatis.xml
mybatis.mapper-locations=classpath:/mybatis/mapper/*.xml

继续

5.编写服务层,调用持久层接口(Mapper接口,比如EmpMapper.java)

	
	5.1 创建EmpService接口,源码如下:

====>>> EmpService.java

package org.it.springboot4.service;

import org.it.springboot4.entity.Emp;
import org.it.springboot4.entity.custom.EmpCustom;

import java.util.List;
import java.util.Map;

public interface EmpService {
    
Emp getEmpById(Integer empno);

List<Map> getEmpByDeptnoSal(EmpCustom empCustom);

Integer insertEmp(Emp emp);

Integer insertGetEmp(Emp emp);

Integer deleteEmp(Map paramMap);

Integer updateEmp(Emp emp);
}

继续

5.2 创建EmpService接口的实现类EmpServiceImpl并且通过注解开启事务和进行事务控制
(不需要像以前一样再去配置Spring的事务配置文件了,只需要这个注解就OK,是不是方便了许多),源码如下(下面的事务简述很重要,记得要看):

====>>> EmpServiceImpl.java

package org.it.springboot4.service;

import org.it.springboot4.entity.Emp;
import org.it.springboot4.entity.custom.EmpCustom;
import org.it.springboot4.mapper.EmpMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)
@Service
public class EmpServiceImpl implements EmpService{

@Resource//注入EmpMapper实现类(mybatis默认使用Cglib动态代理生成的EmpMapper接口的实现类)
private EmpMapper empMapper;

@Transactional(readOnly=true)
public Emp getEmpById(Integer empno) {
    Emp emp = this.empMapper.findEmpById(empno);
    return emp;

}

//查询研发部中薪资大于或等于6600的员工
@Override
public List<Map> getEmpByDeptnoSal(EmpCustom empCustom) {
    List<Map>  maps =  this.empMapper.findEmpByDeptnoSal(empCustom);
    return maps;
}

//添加一个新入职的员工
@Override
public Integer insertEmp(Emp emp) {
    //影响的表中记录的条数,默认为空
    Integer num = 0;
    num = this.empMapper.createEmp(emp);
    return num;
}

// 创建并映射当前新增加的员工编号(返回的还是影响的记录数)
public Integer insertGetEmp(Emp emp) {
    Integer iInsert = 0;
    iInsert = this.empMapper.createGetEmp(emp);
    return iInsert;
}

//删除员工
@Override
public Integer deleteEmp(Map paramMap) {
    Integer iDel = 0;
    iDel = this.empMapper.deleteEmp(paramMap);
    return iDel;
}


//更新员工
@Override
public Integer updateEmp(Emp emp) {
    Integer iUpdate = 0;
    iUpdate = this.empMapper.updateEmp(emp);
    return iUpdate;
}

}

继续

		在这里进行事务简述,@Transactional的常用方法(什么ACID概念的就不说了):
		 先来看看这个注解,
		@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)
		说明:
		a.只读:readOnly() ,通常用于在查询方法上@Transactional(readOnly=true),是可以提高
		   		效率的,默认为false
		
		b.事务的传播特性:propagation(),说的直白一点"就是方法在调用的时候是开启一个新事
			务,还是使用原来的事务这一类的操作"
			感觉有点朦胧?这个东西在分布式数据源中就会发挥出明显的威力。
			记得JPA中若果不开启事务,对于修改一类的操作是不成功的。但是在SSM中没有这个要求。
		
		c.事务的隔离级别:isolation(),这个东西是来干嘛的?
			若果你拿它来与线程中的概念进行对比,它就类似于java多线程和并发操作时DB所
			采取的策略。	这个东西,好像需要DB来支持的,不能随意指定隔离级别,你得查看
			你的DB所支持哪些隔离级别。
		
		d.指定的异常及子异常进行事务回滚:rollbackFor(),
		 这个东西笔者常听人说,"哎呀,我这个业务操作失败了怎么部分数据还保存到DB中了"
		若果你指定是的RuntimeException.class像java.text.ParseException是回滚不了的,
		因为它不是RuntimeException的子类。
		
			
6.编写Web层(Controller+视图层)
	请看博文"第2集 SpringBoot一天速成",地址:#更新中...

相关文章:

  • 2022-01-30
  • 2021-10-08
  • 2021-11-23
  • 2021-11-13
  • 2021-07-12
  • 2021-11-10
  • 2021-06-28
  • 2021-12-17
猜你喜欢
  • 2022-12-23
  • 2021-10-18
  • 2022-12-23
  • 2021-11-24
  • 2021-10-23
  • 2021-10-20
  • 2022-12-23
相关资源
相似解决方案