1.首先项目分为五个层

DAO层、ENTITY层、SERVICE层、CONTROLLER层、View层

1、DAO层: 持久层 主要与数据库进行交互

DAO层主要是做数据持久层的工作,主要与数据库进行交互。

DAO层首先会创建DAO接口,接着就可以在模块中就可以调用DAO 的接口进行数据业务的而处理,并且不用关注此接口的具体实现类是哪一个类。DAO 层的数据源和数据库连接的参数都是在配置文件中进行配置的。

2、Entity层: 实体层 数据库在项目中的类

3、Service层:业务层 控制业务

Service层主要负责业务模块的逻辑应用设计。和DAO层一样都是先设计放接口的类,再创建实现的类,然后在配置文件中进行配置其实现的关联。接下来就可以在service层调用接口进行业务逻辑应用的处理。

封装Service层的业务逻辑有利于业务逻辑的独立性和重复利用性。

4、Controller层: 控制层 控制业务逻辑

Controller层负责具体的业务模块流程的控制,其实就是与前台互交,把前台传进来的参数进行处理,controller层主要调用Service层里面的接口控制具体的业务流程,控制的配置也需要在配置文件中进行

5、View层: 此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示,

Util工具类:存放DAO、JDBC工具类

Conroller层和Service层的区别是:Controlle层负责具体的业务模块流程的控制;Service层负责业务模块的逻辑应用设计;

总结:在具体的项目中,其流程为:Controller层调用Service层的方法,Service层调用Dao层中的方法,其中调用的参数是使用Entity层进行传递的。总的来说这样每层做什么的分类只是为了使业务逻辑更加清晰,写代码更加方便,所以有时候也需要根据具体情况来,但是大体的都是这样处理的,因为它其实就是提供一种规则,让你把相同类型的代码放在一起,这样就形成了层次,从而达到分层解耦、复用、便于测试和维护的目的。

2 项目文件整体截图

java项目数据层设计_SQL

java项目数据层设计_java项目数据层设计_02

3 项目代码

3.1util层工具类

JDBCUtil.java

里面用到了druid.properties配置文件来加载驱动,用数据库连接池来获取连接对象dataSource

package util;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

/**
 * JdbaUtil功能概述
 *  1.程序预处理驱动问题和连接所需数据
 *  2.获取数据库连接对象
 *  3.关闭数据库操作所需资源
 *
 * @author 陈聪聪
 */
public class JdbcUtil {
    /*
    定义一个DataSource数据库连接池静态成员变量
     */
    private static DataSource dataSource = null;

    static {
        try {
            /*
            加载druid.properties文件
             */
            Properties properties = new Properties();
            /*
            JdbcUtil.class.getClassLoader()获取类加载器
            在类加载位置检索"druid.properties"文件,创建对应文件的InputStream字节输入流对象
             */
            properties.load(JdbcUtil.class.getClassLoader().getResourceAsStream("druid.properties"));

            /*
                DruidDataSourceFactory.createDataSource(properties)
                通过DruidDataSourceFactory Druid数据库连接池工厂类,创建新的数据库连接对象
                    */
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*
    直接在JdbcUtil工具类中创建ComboPooledDataSource类对象,返回值类型
    可以认为是DataSource 数据库连接池对象

     private static DataSource dataSource = new ComboPooledDataSource();
    */

    /**
     * 获取Connection 数据库连接对象
     *
     * @return Connection 对象。如果没有获取到数据库连接对象,返回null
     */
    public static Connection getConnection() {
        Connection connection = null;

        try {
            /*
             这里是通过数据库连接池获取数据库连接对象
             数据库连接池中的对象在调用close方法时,会被拦截,不是真的关闭
             数据库连接对象,而是规划给数据库连接池。
            */
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return connection;
    }

    /**
     * 获取当前JdbcUtil工具类中处理得到的数据连接对象
     * @return
     */
    public static DataSource getDataSource(){
        return dataSource;
    }
    public static void close(Connection connection) {
        close(connection, null, null);
    }

    public static void close(Connection connection, Statement statement) {
        close(connection, statement, null);
    }

    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }

            if (statement != null) {
                statement.close();
            }

            if (connection != null) {
                connection.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭资源使用方法,需要的参数是AutoCloseable接口实现类对象,
     * 不定长参数
     *
     * @param source AutoCloseable... 不定长参数
     */
    public static void close(AutoCloseable... source) {
        // 不定长参数在方法中就是一个数组!!!
        for (AutoCloseable closeable : source) {
            try {
                closeable.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

druid.properties

# 文件名 druid.properties 存储在src目录下
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb2
username=root
password=root

# 初始化数据库连接池容量
initialSize=10

# 最大容量
maxActive=30

# TimeOut 等待超时时间
maxWait=2000

BaseDAO.java

里面使用了轻量级ORM框架的dbUtils的querryRunner对象调用开源query、update方法来与数据库进行交互

package util;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class BaseDao {
    /**
     * 当前BaseDao中使用的DbUtils核心类 QueryRunner对象,并且使用
     * 静态成员变量处理方式在类文件加载阶段完成对象的创建过程,简化
     * 后期代码逻辑
     */
    private static QueryRunner queryRunner = new QueryRunner(JdbcUtil.getDataSource());

    /**
     * 通用查询操作方法,处理insert,delete,update 对应SQL语句
     *
     * @param sql        String SQL语句
     * @param parameters SQL语句对应的参数列表,不定长参数
     * @return 当前SQL语句操作对应当前数据库的受到影响的行数
     * @throws SQLException SQL异常
     */
    public int update(String sql, Object... parameters) throws SQLException {
        return queryRunner.update(sql, parameters);
    }

    /**
     * 查询用户指定符合JavaBean规范的类对象。
     *
     * @param sql        select查询语句,查询数据行结果为一行或则empty
     * @param cls        用户指定查询结果对象的类对象类对象类型的Class
     * @param parameters 对应当前SQL语句的参数,为不定长参数
     * @param <T>        泛型约束数据类型
     * @return 用户通过Class<T> cls约束的数据类型,要求符合JavaBean规范
     * @throws SQLException SQL异常
     */
    public <T> T queryBean(String sql, Class<T> cls, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new BeanHandler<>(cls), parameters);
    }

    /**
     * 查询用户指定符合JavaBean规范的类对象List集合。
     *
     * @param sql        select查询SQL语句
     * @param cls        用户指定的数据类型,要求符合JavaBean规范
     * @param parameters 对应SQL语句的参数,为不定长参数
     * @param <T>        泛型约束数据类型
     * @return 包含用户指定数据类型的List集合对象
     * @throws SQLException SQL异常
     */
    public <T> List<T> queryBeanList(String sql, Class<T> cls, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new BeanListHandler<>(cls), parameters);
    }

    /**
     * 查询用户指定SQL语句对应结果集数据行的Object数组,一般用于多表查询情况下的数据处理。
     *
     * @param sql select查询SQL语句
     * @param parameters 对应SQL语句的参数,为不定长参数
     * @return 包含数据行所有数据的Object类型数组
     * @throws SQLException SQL异常
     */
    public Object[] queryArray(String sql, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new ArrayHandler(), parameters);
    }

    /**
     * 查询用户指定SQL语句结果集所有数据行的Object数组,一般用于多表查询情况下的数据处理。
     *
     * @param sql select查询SQL语句,结果为多行数据
     * @param parameters 对应SQL语句的参数,为不定长参数
     * @return List集合中包含所有数据行对应的Object数组数据
     * @throws SQLException SQL异常
     */
    public List<Object[]> queryArrayList(String sql, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new ArrayListHandler(), parameters);
    }

    /**
     * 查询SQL语句对应结果集数据行的Map双边队列,字段对应Key为String类型,数据对应Value为
     * Object类型。
     *
     * @param sql select查询语句
     * @param parameters 对应SQL语句的参数,为不定长参数
     * @return Map<String, Object>包含所有数据行对应数据的Map双边队列
     * @throws SQLException SQL异常
     */
    public Map<String, Object> queryMap(String sql, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new MapHandler(), parameters);
    }

    /**
     * 查询SQL语句对应结果集所有数据行的Map双边队列List集合,字段对应Key为String类型,数据对应Value为
     * Object类型。每一行数据都是一个Map,所有的数据行存储在一个List集合中
     *
     * @param sql select查询语句
     * @param parameters 对应SQL语句的参数,为不定长参数
     * @return List<Map<String, Object>> List集合,包含每一行数据对应的Map双边队列
     * @throws SQLException SQL异常
     */
    public List<Map<String, Object>> queryMapList(String sql, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new MapListHandler(), parameters);
    }
}

c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<!-- 默认配置,只可以出现一次 -->
	<default-config>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb2</property>
		<property name="user">root</property>
		<property name="password">root</property>

		<!-- 连接超时设置30秒 --> 
		<property name="checkoutTimeout">3000</property>
		<!-- 30秒检查一次connection的空闲 -->
		<property name="idleConnectionTestPeriod">30</property>
		<!--初始化的池大小 --> 
		<property name="initialPoolSize">10</property>
		<!-- 最多的一个connection空闲时间 -->  
		<property name="maxIdleTime">30</property>
		<!-- 最多可以有多少个连接connection -->
		<property name="maxPoolSize">30</property>
		<!-- 最少的池中有几个连接 -->
		<property name="minPoolSize">10</property>
		<!-- 批处理的语句
		 -->
		<property name="maxStatements">50</property>
		<!-- 每次增长几个连接 -->
		<property name="acquireIncrement">3</property>

	</default-config> 
</c3p0-config>

3.2 Entity层

Student.java

对应数据库中表中各字段的属性

package com.cc.project.entity;

public class Student {
    private int id;
    private String name;
    private int age;
    private boolean gender;
    private int score;

    public Student(){

    }
    public Student(String name, int age, boolean gender, int score) {
    }

    public Student(int id, String name, int age, boolean gender, int score) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.score = score;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean isGender() {
        return gender;
    }

    public void setGender(boolean gender) {
        this.gender = gender;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", score=" + score +
                '}';
    }
}

3.2 DAO层(与数据库交互)

StudentDao.interface

接口中定义符合规范的操作数据库的方法,数据持久层

package com.cc.project.dao;

import com.cc.project.entity.Student;

import java.util.List;

/**
 * StudentDao接口,是Student数据持久层接口
 * 用于规范关于Student类对象操作数据库的方式方法。
 */
public interface StudentDao {
    /**
     * 添加学生对象到当前数据库中保存对应数据
     *
     * @param student Student类对象
     * @return 当前SQL语句操作对应数据库的影响行数
     */
    int addStudent(Student student);

    /**
     * 根据指定ID删除对应的Student类对象
     *
     * @param id 用户指定ID号
     * @return 当前SQL语句操作对应数据库的影响行数
     */
    int deleteStudent(int id);

    /**
     * 更新对应学生的数据库信息
     *
     * @param student Student类对象
     * @return 当前SQL语句操作对应数据库的影响行数
     */
    int updateStudent(Student student);

    /**
     * 找出对应id号的Student类对象
     *
     * @param id 用户指定的ID号
     * @return 找到返回Student类对象,未找到返回null
     */
    Student findStudent(int id);

    /**
     * 找出当前数据库中的所有学生对象List集合
     *
     * @return List集合,包含所有的Student类对象,如果当前数据库中数据行为空
     *         返回null
     */
    List<Student> findAll();
}

StudentDaoImpl.java

实现类继承BaseDao的方法实现StudentDao接口内定义的方法,方法内提供SQL语句

package com.cc.project.dao.impl;

import com.cc.project.dao.StudentDao;

import com.cc.project.entity.Student;
import util.BaseDao;

import java.sql.SQLException;
import java.util.List;

/**
 * StudentDaoImpl 数据持久化操作的实现类
 *      1. 继承BaseDao,可以使用BaseDao提供的通用方法
 *      2. 遵从StudentDao接口,可以用于其他方法中使用。
 */
public class StudentDaoImpl extends BaseDao implements StudentDao {
    @Override
    public int addStudent(Student student) {
        String sql = "insert into student(name, age, gender, score) VALUES (?,?,?,?)";
        Object[] parameters = {student.getName(), student.getAge(), student.isGender(), student.getScore()};

        try {
            return super.update(sql, parameters);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return 0;
    }

    @Override
    public int deleteStudent(int id) {
        String sql = "delete from student where id = " + id;

        try {
            return super.update(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return 0;
    }

    @Override
    public int updateStudent(Student student) {
        String sql = "update student set name = ?, age = ?, gender = ?, score = ? where id = ?";
        Object[] parameters = {student.getName(), student.getAge(), student.isGender(), student.getScore(),
                student.getId()};

        try {
            return super.update(sql, parameters);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public Student findStudent(int id) {
        String sql = "select * from student where id = " + id;
        Student student = null;
        try {
            student = super.queryBean(sql, Student.class);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return student;
    }

    @Override
    public List<Student> findAll() {
        String sql = "select * from student";

        try {
            return super.queryBeanList(sql, Student.class);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return null;
    }
}

3.3 Service层(调用Dao层,面向用户交互)

StudentService.interface

面向用户提供操作Student方式,增删改查

package com.cc.project.service;

import java.sql.SQLException;

/**
 * 对外提供关于Student操作服务
 *      1.增加学生
 *      2.开除学生
 *      3.查询指定id学生
 *      4.修改学生信息
 *      5.查询所有学生
 *      6.按照指定条件过滤学生
 *      7.按照指定条件排序学生
 */
public interface StudentService {
    /**
     * 添加学生
     */
    void addStudent() ;

    /**
     * 开除学生
     */
    void removeStudent() ;

    /**
     * 查询指定学生信息
     */
    void findOnestudent();

    /**
     * 修改指定学生信息
     */
    void modifyStudent() ;

    /**
     * 查询所有学生
     */
    void findAllStudent() ;

    /**
     * 过滤条件展示学生信息
     */
    void filterStudent() ;

    /**
     * 按照指定条件展示学生信息
     */
    void sortStudent() ;
}

StudentServiceImpl.java


* 当前StudentServiceImpl实现类中需要操作数据库持久操作* 这里需要StudentDao实现类支持


将操作上传到数据库执行,直接调用StudentDao类的方法

package com.cc.project.service.impl;

import com.cc.project.dao.StudentDao;
import com.cc.project.dao.impl.StudentDaoImpl;
import com.cc.project.entity.Student;
import com.cc.project.service.StudentService;


import java.util.List;
import java.util.Scanner;
public class StudentServiceImpl implements StudentService {

    /**
     * 当前StudentServiceImpl实现类中需要操作数据库持久操作
     * 这里需要StudentDao实现类支持
     */
    private StudentDao studentDao = new StudentDaoImpl();

    private static Scanner sc = new Scanner(System.in);
    @Override
    public void addStudent() {
        System.out.println("请输入学生的姓名:");
        String name = sc.nextLine();

        System.out.println("请输入学生的年龄:");
        int age = sc.nextInt();

        System.out.println("请输入学生的性别:");
        boolean gender = sc.nextBoolean();

        System.out.println("请输入学生的成绩:");
        int score = sc.nextInt();

        Student student = new Student(name, age, gender, score);

        studentDao.addStudent(student);
    }

    @Override
    public void removeStudent() {
        System.out.println("请输入学生的ID号");
        int id = sc.nextInt();

        studentDao.deleteStudent(id);
    }

    @Override
    public void findOnestudent() {
        System.out.println("请输入学生的ID号");
        int id = sc.nextInt();

        System.out.println(studentDao.findStudent(id));
    }

    @Override
    public void modifyStudent() {

        System.out.println("请输入要修改的学生的信息:");
        System.out.println("1.修改学生的姓名:");
        System.out.println("2.修改学生的年龄:");
        System.out.println("3.修改学生的性别:");
        System.out.println("4.修改学生的分数:");

        Student student = new Student();

        int choose = sc.nextInt();
        switch (choose){
            case 1:
                String name = sc.nextLine();
                break;
            case 2:
                int age = sc.nextInt();
                break;
            case 3:
                String gender = sc.nextLine();
                break;
            case 4:
                int score = sc.nextInt();
                break;
        }
        studentDao.updateStudent(new Student());
    }

    @Override
    public void findAllStudent() {
        List<Student> list = studentDao.findAll();
        if (list != null) {
            for (Student stu : list) {
                System.out.println(stu);
            }
        }
    }

    @Override
    public void filterStudent() {
        List<Student> list = studentDao.findAll();

        if (list != null) {
            System.out.println("1. 年龄大于20的");
            System.out.println("2. 成绩小于60的");
            int choose = sc.nextInt();

            switch (choose) {
                case 1:
                    list.stream()
                            .filter(s -> s.getAge() > 20)
                            .forEach(System.out::println);
                    break;
                case 2:
                    list.stream()
                            .filter(s -> s.getScore() < 60)
                            .forEach(System.out::println);
                    break;

            }
        }
    }

    @Override
    public void sortStudent() {
        List<Student> list = studentDao.findAll();

        if (list != null) {
            System.out.println("1. 年龄升序");
            System.out.println("2. 成绩降序");
            int choose = sc.nextInt();

            switch (choose) {
                case 1:
                    list.stream()
                            .sorted((s1, s2) -> s1.getAge() - s2.getAge())
                            .forEach(System.out::println);
                    break;
                case 2:
                    list.stream()
                            .sorted((s1, s2) -> s2.getScore() - s1.getScore())
                            .forEach(System.out::println);
                    break;

            }
        }
    }
}

3.4 Controller层(调用Service层)

用Map键值对方式在前台与用户交互

StudentController.java

package com.cc.project.controller;

import com.cc.project.service.StudentService;
import com.cc.project.service.impl.StudentServiceImpl;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class StudentController {
    private Scanner sc = new Scanner(System.in);

    /**
     * 提供Student范围。StudentService实现类
     */
    private StudentService service = new StudentServiceImpl();

    public void controller() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Map<Integer, String> methodMap = getMethodMap();
        while (true) {
            System.out.println("1. 添加学生 addStudent");
            System.out.println("2. 开除指定学生 removeStudent");
            System.out.println("3. 修改指定学生 modifyStudent");
            System.out.println("4. 查询指定学生 findOneStudent");
            System.out.println("5. 查询所有学生 findAllStudent");
            System.out.println("6. 过滤条件展示学生信息 filterStudent");
            System.out.println("7. 按照指定条件展示学生信息 sortStudent");
            System.out.println("8. 退出");

            int choose = sc.nextInt();
            sc.nextLine();

            if (8 == choose) {
                break;
                /*
                choose不得大于8 不得小于等于0,不然无法在map双边队列中获取对应的数据
                 */
            } else if (choose <= 0 || choose > 8) {
                continue;
            }

            /*
            从Map中跟腱对应的choose获取对应MethodName方法名字,从StudentServiceImpl对应Class对象
            中获取对应的方法Method对象,invoke执行操作
             */
            StudentServiceImpl.class.getMethod(methodMap.get(choose)).invoke(service);
        }
    }

    /**
     * 预处理对应的Map方法双边队列
     *
     * @return Integer类型映射String方法名字的Map双边队列
     */
    private Map<Integer, String> getMethodMap() {
        HashMap<Integer, String> map = new HashMap<>();

        map.put(1, "addStudent");
        map.put(2, "removeStudent");
        map.put(3, "modifyStudent");
        map.put(4, "findOneStudent");
        map.put(5, "findAllStudent");
        map.put(6, "filterStudent");
        map.put(7, "sortStudent");

        return map;
    }

}

3.5 MainProject(调用Controller层)

StudentSystem.java

package com.cc.project.mainproject;


import com.cc.project.controller.StudentController;
import util.MethodEnum;


import java.lang.reflect.InvocationTargetException;

public class StudentSystem {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        new StudentController().controller();
    }
}