Java 如何避免一个类的所有方法都通用的重复代码?
在我们的应用程序中,在DAO层中,每个方法都遵循几乎相同的顺序:Java 如何避免一个类的所有方法都通用的重复代码?,java,dao,duplicate-removal,Java,Dao,Duplicate Removal,在我们的应用程序中,在DAO层中,每个方法都遵循几乎相同的顺序: public List getSomeValue(String[] parameters) { try { //Get connection from pool //Execute procedure //Process resultset } catch (SomeException e) { //Error handling mechanism
public List getSomeValue(String[] parameters) {
try {
//Get connection from pool
//Execute procedure
//Process resultset
} catch (SomeException e) {
//Error handling mechanism
} finally {
//Release connection
}
return someResult;
}
上面代码中的所有注释行都描述了我们正在执行的操作
现在,除了过程-结果集部分,所有内容几乎完全相同
我的问题是,我们能否实现某种设计,这样我们就不必在每个方法中反复编写相同的代码?所以,我们只需要编写结果集处理部分
实用方法已经到位。但同样,我们必须在每个过程中以完全相同的顺序调用它们。我们能不能让这些预定义的方法被自动调用,我们只需要编写不同的部分?我甚至不确定这是否可能
注意:我们不能使用任何像Hibernate这样的ORM工具。您可以创建一个基类,在那里编写通用方法,然后从基类继承类,这样每个子类都会继承它们
如果没有选择拥有一个超类(受框架或其他一些原因的限制),那么可以编写一个实用程序类,该类具有用于公共功能的静态方法 为什么不传入一个
映射器
,它知道如何将结果集
转换为所需的元素列表。例如:
public List<T> getSomeValue(String[] parameters, ResultSetMapper<T> mapper) {
try {
//Get connection from pool
//Execute procedure
//Process resultset
return mapper.convert(resultSet);
} catch (SomeException e) {
//Error handling mechanism
} finally {
//Release connection
}
}
interface RowMapper<T> {
List<T> convert(ResultSet resultSet);
}
public List getSomeValue(字符串[]参数,结果映射器){
试一试{
//从池中获取连接
//执行程序
//过程结果集
返回mapper.convert(resultSet);
}捕获(某些例外){
//错误处理机制
}最后{
//释放连接
}
}
接口行映射器{
列表转换(ResultSet ResultSet);
}
您将传入不同的mapper
实现,而getSomeValue
方法将保持不变,因此您只需要它的一个实现
如果您在项目中使用Spring,您可以使用它的
ResultSetTextRactor
或RowMapper
类来做类似的事情
Object doSomething(){
return doInTransaction(trans -> {
return trans.load();
});
}
其中InTrans
是
public interface InTrans<T> {
T call(Transaction transaction);
}
或者,您可以使用
Spring
中的声明性事务。这使用了talex
在其回答中提出的相同原则,只是对于您正在寻找的内容,我相信您想要的是使用ResultSet
作为输入的功能接口(或其他类似接口)
因此,基本上,所有连接的获取、过程执行、结果集的循环和异常处理都保留在一个方法中,不会重复。当调用该方法时,传入将处理每一行的代码
它看起来像这样:
public void callingCode() {
List<String> someList = new ArrayList<>();
performQuery(
"SELECT * FROM ...",
new String[]{"param1", "param2"},
rs -> {
try {
// process your row here.
someList.add(rs.getString("somecolumn"));
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}
public void performQuery(String query, String[] parameters, Consumer<ResultSet> processRow) {
try {
//Get connection from pool
//Execute procedure
ResultSet rs = null; // pretend this comes from the procedure call.
//Process resultset
while (rs.next()) {
processRow.accept(rs);
}
} catch (Exception e) {
//Error handling mechanism
} finally {
//Release resources
}
}
调整代码:
public void callingCode() {
List<String> someList = new ArrayList<>();
performQuery(
"SELECT * FROM ...",
new String[]{"param1", "param2"},
rs -> {
// process your row here.
someList.add(rs.getString("somecolumn"));
});
}
public void performQuery(String query, String[] parameters, ResultSetConsumer rsConsumer) {
try {
//Get connection from pool
//Execute procedure
ResultSet rs = null; // pretend this comes from the procedure call.
//Process resultset
while (rs.next()) {
rsConsumer.processRow(rs);
}
} catch (Exception e) {
//Error handling mechanism
} finally {
//Release resources
}
}
public void callingCode(){
List someList=new ArrayList();
表演(
“从…中选择*,
新字符串[]{“param1”,“param2”},
rs->{
//在这里处理您的行。
add(rs.getString(“somecolumn”);
});
}
公共void性能查询(字符串查询、字符串[]参数、结果消费者rsConsumer){
试一试{
//从池中获取连接
//执行程序
ResultSet rs=null;//假设它来自过程调用。
//过程结果集
while(rs.next()){
rsConsumer.processRow(rs);
}
}捕获(例外e){
//错误处理机制
}最后{
//释放资源
}
}
我想到了可重用的方法或继承的超类方法,为什么不将重复的代码移到方法(可能在抽象父类中)上,比如:Connection getConnectionFromPool()
和void executeProcedure()
?这些方法已经存在了。但同样,我们必须在每个过程中以完全相同的顺序调用它们。我们能不能让这些预定义的方法被自动调用,我们只需要编写不同的部分?我甚至不确定这是否可能。如果我们有两个方法getSomeValue1(),getSomeValue2(),我们不需要复制东西吗?你说过这些方法做的事情完全一样,只是转换结果集。如果这是真的,您只需要1个实现的getSomeValue
,并传入不同的映射程序。我会研究一下,然后再给您回复。谢谢
public interface ResultSetConsumer {
void processRow(ResultSet rs) throws SQLException;
}
public void callingCode() {
List<String> someList = new ArrayList<>();
performQuery(
"SELECT * FROM ...",
new String[]{"param1", "param2"},
rs -> {
// process your row here.
someList.add(rs.getString("somecolumn"));
});
}
public void performQuery(String query, String[] parameters, ResultSetConsumer rsConsumer) {
try {
//Get connection from pool
//Execute procedure
ResultSet rs = null; // pretend this comes from the procedure call.
//Process resultset
while (rs.next()) {
rsConsumer.processRow(rs);
}
} catch (Exception e) {
//Error handling mechanism
} finally {
//Release resources
}
}