三层架构的意义
还记得我当初学 Java 操作数据库的示例代码时要做的步骤:
- 连接数据库
- 编译 sql
- 执行 sql,获取结果集
- 遍历结果集,封装对象
- 得到的结果(或集合)返回出去
- 在 Servlet 中调用写好的函数,将结果转换成 JSON 字符串返回给前端
public class JdbcMySql {
private String url = "jdbc:mysql://127.0.0.1:3306/test";
private String username = "root";
private String password = "123456";
private String driver = "com.mysql.jdbc.Driver";
private Connection connection;
// 编译 sql 语句的
private Statement statement;
public JdbcMySql() {
try {
// 1. 构造函数最先执行,开始寻找 mysql 的驱动
Class.forName(driver);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public void open() {
// 2. 执行 open 函数,打开连接,连接 mysql 数据库
try {
connection = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 3. 打开通道之后,我们就要执行数据库操作了
// crud
// 查询数据库 user 表
public List<User> query() {
List<User> list = new ArrayList<>();
try {
// 1. 获取编译 sql 的对象
statement = connection.createStatement();
String sql = "select * from t_users";
// 2. 执行 sql,得到结果
ResultSet resultSet = statement.executeQuery(sql);
// 3. 循环遍历结果
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("username");
String pwd = resultSet.getString("password");
// 4. 封装数据为对象
User user = new User();
user.setId(id);
user.setUsername(name);
user.setPassword(pwd);
// 5. 添加到集合中
list.add(user);
}
// 6. 得到的集合返回出去
return list;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
在写 query
函数时,我们并没有业务在里面,所谓业务就是一堆判断、不合法的获取等等。当涉及到了业务的时候,这个 query
函数代码就变得非常多,通常写一个业务会存在多个步骤,当所有步骤都写在一个函数里面,代码的阅读性就变得非常地低了。
所以,我们上面的代码可以拆分步骤,再将这些步骤组装到函数里面。
add:[private List<User> extractUserDataFromSet(ResultSet set) throws SQLException {
List<User> list = new ArrayList<>();
while (set.next()) {
int id = set.getInt("id");
String name = set.getString("username");
String pwd = set.getString("password");
User user = new User();
user.setId(id);
user.setUsername(name);
user.setPassword(pwd);
list.add(user);
}
return list;
}]:add
public List<User> query() {
try {
statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from t_users");
lit:[return extractUserDataFromSet(resultSet);]:lit
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
阅读函数名称 extractUserDataFromSet
,就可以知道这个函数是专门做从结果集中抽取用户数据的。这样可以让我们一目了然,这个函数在做什么。当有其他处理步骤时,再写一个简明扼要的函数名称,去专门做这个事情。
tip:[start]
虽然这个函数抽离出来之后可能从始至终使用一次,但是可以提升我们代码的可阅读性和维护性。注意,这种函数的抽离并不会降低代码的耦合度。
tip:[end]
假如,有一个非常简单的业务处理:
public List<User> query() {
try {
statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from t_users");
List<User> list = extractUserDataFromSet(resultSet);
add:[if (list.isEmpty()) {
System.out.println("查询不到数据");
return null;
} else {
return list;
}]:add
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
如果这个业务非常复杂,代码也很多,不可能一直在这个类继续添加函数去处理,随着功能增加,我们的这个类就显得非常冗余、混乱。
所以,将代码分层书写就变得非常重要!
- Controller Service Daocontroller service dao controller service java dao controller service spring java springboot controller repository service controller作用service pojo springboot controller框架service springboot controller service entity nifi controller service controller service controller service还是