基于ssm的service层实现文件上传和文件删除功能(图文超详细)

最近毕设遇到一个需求:实现文件的上传功能,并且把上传信息插入数据库,删除文件,并把文件信息从数据删除。(基于service层)

本人的实现方案:
由于没有文件服务器,上传的文件路径为:src/main/webapp/WEB-INF/员工编号/文件名,因为要上传文件,并且文件信息要保存到数据库中,所以用到spring框架提供的事务(本例用声明式事务),需要数据回滚。

下面给出了数据表关系:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
员工表:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
部门表:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
文件表:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
三表关系:
员工表有个外键部门号引用部门表的部门号,文件表有个外键引用到员工表的员工号。

对应的实体类(javaBean,省略构造器,get和set方法)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)

关于设置实体类对应映射关系的字段,可以参考我之前发的博客:
https://blog.****.net/C_bianchengxiaobai/article/details/100632418

先写文件上传功能
给出dao以及对应的mapper里的sql语句:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
很简单,只是写了插入的sql语句。通过测试,插入数据成功(模拟上传文件信息到数据库):
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)

解释一下测试方法中的红色两个框方法:
第一个红框是通过员工号查询到员工信息并返回,用作文件类的setEmployee方法参数,也可以实例一个Employee,用se方法t模拟员工信息。
第二个红框是自定义的一个工具类,第一个参数为要传入的Date类型,第二个参数指定时间格式,并返回String类型的格式,下面是该实现方法:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)

以上只是把文件信息保存到数据库,下面开始写Service层的文件上传方法:
先给出代码:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
第一个参数为自定义的文件信息,用于保存到数据库,第二个参数为要上传的文。
实现类:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
上处也圈了两个红框:
第一个红款表示该上传方法是被事务管理的,也就是说,在此方法,数据在插入之后,如果发生了异常(一般是运行时异常)那么事务就会把数据就会回滚到插入之前(数据库不会有该数据),保证了文件上传和数据库插入数据的一致性。

第二框的第一行就是调用Dao把文件信息插入到数据库。为了方便,自定义一个工具类MyFileUtils,提供了文件路径最后一行是common-io包下的工具类,目的是把上传文件拷贝到指定的目录下。

下面给出测试方法:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
查看数据库:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
查看文件
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
功能出来了,如果想到只有功能,那么以下的就可以不用看了。

接下来,考虑问题:

问题一:在插入文件信息和插入上传文件之间,出现运行时异常。

下面模拟问题一:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
和之前没什么不一样,就是多了一行 1/0,用来模拟异常
运行测试方法:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
(改成上传b.txt)

基于ssm的service层实现文件上传和文件删除功能(图文超详细)
现在查看数据库文件信息和文件上传:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
明明异常是出现在插入数据之后的,为什么没有上传呢,原因很简单,因为该方法是事务管理的,当出现异常时,数据就会回滚。

如果不采用事务(也就是不用@Transactional)来看下面的例子:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
运行测试方法:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
**
这就会导致数据库有文件信息但是文件上传失败,导致数据的不一致,所以要加事务管理!!!**

问题二:在插入文件信息和插入上传文件之后,出现运行时异常。

模拟问题二:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
开启事务管理,模拟异常

测试方法(上传c.txt),运行:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
问题来了,这不是事务管理的方法,出现异常了为什么不会回滚?
下面给出spring官网的解释:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
嗯。。。翻译下:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
(翻译之后看着也有点奇怪~~)
大概意思就是,只有运行时异常,数据才会回滚,
这里还有一个重要的概念:**只有进行对数据库的操作才会有事务一些特性!!!**所以此例的问题是数据回滚了,文件上传并没有回滚。

解决方案:先给出代码:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
重点看红色框,改写为在数据库插入信息之后才做文件的上传的功能,如果数据库信息没有插入到数据库,就不会上传文件。在进行文件上传中如果出现的异常(运行时)那么就上传会终止,数据信息也会回滚,保证了上传文件和插入数据的一致性。
下面进行测试:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
以上是文件上传的功能。

删除文件的实现和文件上传的实现相似,给出代码:

dao和对应的mapper:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)

对应的service
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
实现类:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
先看第一个红色的大框,进入的条件为登陆的员工号等于文件的员工号 &&
要删除的文件存在,否则返回0,。
第二个红框为当数据库里的文件信息成功删除后,再删除文件,此处删除文件使用的common-io下的工具类,否则返回0。
第三个红框,为删除文件返回一个标识,删除成功返回true,否则返回false,若成功删除,则返回re,否则抛出一个运行时异常,目的是为了让事务回滚,保证数据的一致性。

测试删除方法(模拟删除a.txt):
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
运行前:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
运行后:
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
发现id为34的文件信息已经被删除,
基于ssm的service层实现文件上传和文件删除功能(图文超详细)
文件a.txt也被删除。

像上传一样,考虑两个问题:
问题一:异常出现在删除文件数据信息和删除文件之间:
基于ssm的service层实现文件上传和文件删除功能(图文超详细) 由于是事务管理的方法在删除数据库文件信息后出现异常,此时还没执行删除文件,所以数据回滚。

问题二:异常出现在删除文件数据信息和删除文件之后:
删除文件用的是comm-io包下的FileUtils.deleteQuietly()方法,此方法没有任何异常,只有返回标识是否成功,如果返回为false,也就是文件删除失败,这里自定义抛出RuntimeException(),让事务回滚,保证了数据的一致性。(此方法有个bug,因为是自定义抛出异常,所以查不出真正的异常)

对此,功能完成。

附上spring关于事务的文档:
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/data-access.html#transaction-declarative-rolling-back