不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。
前言
本系统是基于之前写的水果库存基础版的基础上进行技术迭代,如果想了解基础版小伙伴可点击此:水果库存系统(基础版)。本次为水果库存系统的进阶版,那么和基础版有何不同呢?接下来介绍一下:
1. 使用Spring中IOC思想,把创建对象交给Spring(框架)管理。
2. 使用Spring里的模板JdbcTemplate实现与持久化技术的交接。
3. 使用MySQL来存储数据,真正关闭系统数据依旧存在的持久化效果。
以上就是本次升级后的系统与基础版的最大区别,那么废话不多说,先演示,后分析。
一、项目演示
以上就是本系统的全部功能,看效果的话和基础版的差别不是很大,如果真看表面效果的话,那么就是退出系统,再开启系统,里面保存的数据会一直存在,除非手动删除。那么接下来我们的来看看这个系统的内部结构。
二、项目分析
首先先聊聊本次系统使用到了什么技术。先说说项目管理功能maven,因为要使用第三方的库,比如Spring、MySQL、JDBC驱动,为了版本一致性和管理的灵活性,本次使用maven管理第三方工具包;然后就是编译器使用eclipse(也可以切换为iade);然后技术就是Spring使用的版本是5.x,MySQL使用的是8.x的。最后就是项目结构如下:
这里按照三层架构的模式来编写该系统。三层架构即数据访问层(持久层)、业务逻辑层(业务层)、视图控制层(控制层)。然后其他的就是实体类,工具类(上图也有标注)。那么在上代码之前,我们先做一点准备工具,得把maven环境搭建好。
以上就是使用eclipse创建maven的全部过程,然后在生成的maven项目中找到pom.xml文件,把下面的代码复制上去就完成了:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nan</groupId>
<artifactId>fruitSys</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
</dependencies>
</project>
环境准备完毕,但是还有一个重要的点,就是数据库还没准备,接下来就是准备数据库了,数据库的设计如下所示:
准备工作到这里就基本完成了,接下来就是上代码。
三、上代码
我们按照数据库到视图层的顺序一一填充代码。
我们先创建Java映射类,作用是对应数据库中的数据。
package com.pojo;
/**
* @author Ban 水果实体类
*/
public class Fruit {
private Integer id; // 水果编号
private String name; // 水果名称
private double price; // 水果价格
private String described; // 描述
/* 构造方法 */
public Fruit(String name, double price, String described) {
this.name = name;
this.price = price;
this.described = described;
}
public Fruit(Integer id, String name, double price, String described) {
this.id = id;
this.name = name;
this.price = price;
this.described = described;
}
public Fruit() {
}
/* get、set方法 */
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getDescribed() {
return described;
}
public void setDescribed(String described) {
this.described = described;
}
/* toString方法 方便打印数据 */
@Override
public String toString() {
return "编号=" + id + ", 名称=" + name + ", 价格=" + price + ", 描述=" + described;
}
}
这里需要注意的是Java属性名要和数据库里的字段名保持一致,不然会导致找不到而程序执行失败。接下来就是Dao层,持久层的代码。
package com.dao;
import com.pojo.Fruit;
import java.util.List;
/**
* 持久层接口
*/
public interface FruitDao {
/*新增库存*/
int addFruit(Fruit fruit);
/*查询库存*/
List<Fruit> selectFruit();
/*根据水果编号查询库存*/
Fruit fruitById(Integer id);
/*修改库存*/
int updateFruit(Fruit newFruit);
/*删除库存*/
int deleteFruit(Integer id);
}
dao实现类
package com.dao;
import com.pojo.Fruit;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.util.List;
public class FruitDaoImpl implements FruitDao {
//定义jdbcTemplate模板
private JdbcTemplate jdbcTemplate;
//在spring容器里获取jdbcTemplate
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/*新增水果*/
@Override
public int addFruit(Fruit fruit) {
//准备SQL
String sql = "insert into fruit(name,price,described) values (?,?,?)";
//获取sql参数
Object[] params = new Object[]{fruit.getName(),fruit.getPrice(),fruit.getDescribed()};
//执行jdbcTemplate 进行新增操作
int num = jdbcTemplate.update(sql, params);
return num;
}
/*查询水果*/
@Override
public List<Fruit> selectFruit() {
//准备SQL
String sql = "select * from fruit";
//映射转换器
RowMapper rowMapper = new BeanPropertyRowMapper<Fruit>(Fruit.class);
//执行查询操作
return jdbcTemplate.query(sql,rowMapper);
}
/*根据编号id查询水果*/
@Override
public Fruit fruitById(Integer id) {
//默认没有查询到
Fruit fruit = null;
try {
String sql = "select * from fruit where id =?";
RowMapper<Fruit> rowMapper = new BeanPropertyRowMapper<Fruit>(Fruit.class);
fruit = jdbcTemplate.queryForObject(sql, rowMapper, id);
}catch (EmptyResultDataAccessException e){
//没有查询到对应的水果
}
return fruit;
}
/*更新水果*/
@Override
public int updateFruit(Fruit newFruit) {
String sql = "update fruit set name=?,price=?, described=? where id =?";
//参数
Object[] params = new Object[]{newFruit.getName(),newFruit.getPrice(),newFruit.getDescribed(),newFruit.getId()};
int num = this.jdbcTemplate.update(sql,params);
return num;
}
/*根据id删除水果*/
@Override
public int deleteFruit(Integer id) {
String sql ="delete from fruit where id =?";
int num = jdbcTemplate.update(sql,id);
return num;
}
}
这里使用了面向接口编程,这样写的好处是维护性得到了统一。而这一层就是操作数据库的,使用了Spring框架里面的JdbcTemplate模板,代码里都有注释,这里就不啰嗦了。那么接下来就是业务层了:
package com.service;
import com.pojo.Fruit;
/**
*
* @author Ban
* 水果库存业务层接口
*
*/
public interface FruitService {
/*新增库存*/
int addFruit(Fruit fruit);
/*查询库存*/
void selectFruit();
/*根据水果编号查询库存*/
String selectById(Integer id);
/*修改库存*/
void updateFruit(Fruit newFruit);
/*删除库存*/
void deleteFruit(Integer id);
}
业务层实现类
package com.service;
import com.dao.FruitDaoImpl;
import com.pojo.Fruit;
import com.util.SpringBean;
import java.util.List;
/**
* @author Ban
* 水果库存逻辑类
*/
public class FruitServiceImpl implements FruitService {
//获取持久层
private FruitDaoImpl fruitDao;
//水果实体类
private Fruit fruit;
//使用setter方法注入
public void setFruitDaoImpl(FruitDaoImpl fruitDaoImpl) {
this.fruitDao = fruitDaoImpl;
}
/**
* 新增库存
*/
public int addFruit(Fruit fruit) {
//在spring容器中获取对象fruitDaoImpl
fruitDao = (FruitDaoImpl)SpringBean.getSpringBean("fruitDaoImpl");
//获取水果信息
Integer id = fruit.getId();
String name = fruit.getName();
double price = fruit.getPrice();
String described = fruit.getDescribed();
//创建一个水果类并生产水果信息
Fruit fruit1 = new Fruit(name, price, described);
//把水果放入仓库 并返回受影响的行数
return fruitDao.addFruit(fruit1);
}
/**
* 查询库存
*/
public void selectFruit() {
FruitDaoImpl fruitDao = (FruitDaoImpl)SpringBean.getSpringBean("fruitDaoImpl");
List<Fruit> fruits = fruitDao.selectFruit();
if (fruits.size() == 0 || fruits == null) {
System.out.println("库存空空如也~~~");
return;
}
//遍历查询
for (Fruit fruit : fruits) {
//直接打印
System.out.println(fruit.toString());
}
}
/**
* 根据水果编号查询对应的水果库存
*/
public String selectById(Integer id) {
Fruit fruit1 = fruitDao.fruitById(id);
//判断
if (null != fruit1) {
return "200";
}
return "-1";
}
/**
* 根据水果编号修改对应库存信息
*/
public void updateFruit(Fruit newFruit) {
int i = fruitDao.updateFruit(newFruit);
if (i > 0) {
System.out.println("修改成功");
}
return;
}
/**
* 根据水果编号删除对应的库存
*/
public void deleteFruit(Integer id) {
//删除水果库存
int i = fruitDao.deleteFruit(id);
if (i > 0) {
System.out.println("操作成功");
}else {
System.out.println("该编号对应的水果不存在!");
}
return;
}
}
关于依赖注入的是需要一个配置文件的,咱们放到后面再说,我们先把整体业务流程捋下来。接下来就是视图层了,也就是controller:
package com.controller;
import com.pojo.Fruit;
import com.service.FruitServiceImpl;
import com.util.SpringBean;
import java.util.Scanner;
/**
* 水果库存系统的视图层
*/
public class View {
//创建水果库存逻辑类
private FruitServiceImpl fruitService;
public void setFruitService(FruitServiceImpl fruitService) {
this.fruitService = fruitService;
}
//水果库存系统视图设置
public void getView(Scanner sc, String inputUser) {
//从Spring容器中获取fruitServiceImpl对象
fruitService = (FruitServiceImpl)SpringBean.getSpringBean("fruitServiceImpl");
//判断用户输入的信息进行不同场景的设计
switch (inputUser) {
case "1": //新增库存
System.out.println("请您根据下面的指示进行操作:");
System.out.print("请输入水果名称:");
String name = sc.next();
System.out.print("请输入水果价格:");
double price = sc.nextDouble();
System.out.print("请输入水果描述:");
String desbriced = sc.next();
//存储水果的对象并把水果信息存入其中
Fruit fruit = new Fruit(name, price, desbriced);
//调用逻辑类添加库存
int count = fruitService.addFruit(fruit);
//判断是否新增成功
if(count <1) {
System.out.println("新增失败!");
}else {
System.out.println("新增成功!");
}
break;
case "2": //查询库存
System.out.println("正在查询...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("<===============水果库存列表===============>");
fruitService.selectFruit();
System.out.println("<================库存列表=================>");
System.out.println(""); //换行
break;
case "3": //修改库存
System.out.println("请输入您要修改的水果编号:");
Integer uId = sc.nextInt();
//在仓库里查询一边是否存在
String msg = fruitService.selectById(uId);
if ("200".equals(msg)) {
//存在,可以修改
System.out.println("请您根据下面的指示进行操作:");
System.out.print("请输入水果名称:");
String uname = sc.next();
System.out.print("请输入水果价格:");
double uprice = sc.nextDouble();
System.out.print("请输入水果描述:");
String udesbriced = sc.next();
//存储水果的对象并把水果信息存入其中
Fruit uFruit = new Fruit(uId,uname, uprice, udesbriced);
//调用逻辑类添加库存
fruitService.updateFruit(uFruit);
} else {
System.out.println("您输入的水果编号不存在");
}
break;
case "4": //删除库存
System.out.println("请输入您要删除的水果编号:");
Integer fid = sc.nextInt();
//调用逻辑类
fruitService.deleteFruit(fid);
break;
case "5": //退出系统
System.out.println("系统已退出");
System.exit(0);
default: //其他不存在操作
System.out.println("您输入的操作不存在!");
break;
}
}
}
本类是编写视图控制的,是与用户操作交互的逻辑,接下来就是程序入口了:
package com.controller;
import java.util.Scanner;
/**
* 水果库存的主菜单
*
* @author Ban
*/
public class Main {
public static void main(String[] args) {
while (true) {
// 设置菜单项
System.out.println("<=====欢迎使用水果库存系统======>");
System.out.println("本系统菜单功能如下:");
System.out.println("【1】新增库存");
System.out.println("【2】查询库存");
System.out.println("【3】修改库存");
System.out.println("【4】删除库存");
System.out.println("【5】退出系统");
//使用扫描器 获取用户输入的信息
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要选择的操作:");
String inputUser = sc.next();
//调用视图
new View().getView(sc, inputUser);
}
}
}
单独写一个程序入口,然后调用视图业务,这样实现了解耦,也使代码看起来更精简了。那么接下来就是重点了,在本系统中,我们可以看到,对象基本不是我们使用new关键字创建出来的,而是让框架Spring里获取的,那么Spring如何存储呢。在基础版的时候,我们需要自己创建对象,然后放进一个集合容器里面,而且现在我们来看看如何把对象交给Spring来管理。
我们来观察maven项目的结构,我们要在src/main/resources中创建一个xml文件,文件名可以自定义,我这里的为:applicationContext,编写的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--1.配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--数据库驱动-->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<!--连接的数据库url-->
<property name="url" value="jdbc:mysql:///mydb?useUnicode=true&useSSL=false&serverTimezone=UTC&characterEncoding=utf-8"/>
<!--连接的数据库用户-->
<property name="username" value="root"/>
<!--连接的数据库密码-->
<property name="password" value=""/>
</bean>
<!--2.配置JDBC模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--默认必须使用数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--3.配置注入类-->
<bean id="fruitDaoImpl" class="com.dao.FruitDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!-- 依赖注入bean -->
<bean id="fruitServiceImpl" class="com.service.FruitServiceImpl">
<property name="fruitDaoImpl" ref="fruitDaoImpl"/>
</bean>
<!-- 把View类交给spring管理,并注入fruitServiceImpl -->
<bean id="view" class="com.controller.View">
<property name="fruitService" ref="fruitServiceImpl"/>
</bean>
</beans>
以上就是配置spring,这样就完成了?不,还有关键的一步,把对象交给spring管理,那么我们还得要获取才行,就好像我们买东西,给钱了,那么东西肯定要拿走的(可能这个比喻不是很恰当)。那么怎么获取容器中的对象呢,我这里封装了一个简单的工具类,放在util包下,代码如下:
package com.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName SpringBean
* @Description 获取spring中的Bean对象
**/
public class SpringBean {
//获取spring容器中的bean
public static Object getSpringBean(String objName){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
return applicationContext.getBean(objName); //根据Baen名称获取Bean
}
}
到这里,水果库存系统的进阶版就完成了,如果有小伙伴已完成以上操作,那么就可以启动程序,展示番自己的成果吧~~
写在最后
以上就是本篇文章的所有内容,在之前的水果库存系统(基础版)的代码上进行升级,相当于技术迭代,使该系统做到数据持久化。如果有兴趣的小伙伴而且对前端有些许基础,可以把视图层改为前端技术。那么本次的内容就到此结束了,如果以上对您有所收获,可动动您的灵动的小手留下足迹。