Java 如何减少数据库访问层中的代码重复?
我是Java新手,我正在尝试实现一个基本的数据库访问层。 我正在使用ApacheDbutils来减少JDBC样板代码,这非常有效 问题是,我的实现对数据库中的每个表使用一个单独的CRUD类,复制这么多功能感觉不好 这是一种可接受的设计吗?如果不是,我可以做些什么来减少代码重复?Java 如何减少数据库访问层中的代码重复?,java,sql,database,generics,dao,Java,Sql,Database,Generics,Dao,我是Java新手,我正在尝试实现一个基本的数据库访问层。 我正在使用ApacheDbutils来减少JDBC样板代码,这非常有效 问题是,我的实现对数据库中的每个表使用一个单独的CRUD类,复制这么多功能感觉不好 这是一种可接受的设计吗?如果不是,我可以做些什么来减少代码重复? 我可以重构我的解决方案以某种方式使用泛型吗 我意识到我可以使用ORM(myBatis、Hibernate等)作为解决方案,但如果我能帮助的话,我想尝试使用DBUtils和普通JDBC 仅供澄清: 假设我有两张桌子 ---
我可以重构我的解决方案以某种方式使用泛型吗 我意识到我可以使用ORM(myBatis、Hibernate等)作为解决方案,但如果我能帮助的话,我想尝试使用DBUtils和普通JDBC 仅供澄清:
假设我有两张桌子
---------------------
User | File
---------------------
userId | fileId
name | path
age | size
---------------------
在我当前的解决方案中,我将创建2个类(UserStore、FileStore)和
每个类将实现类似的基本CRUD方法:
protected boolean Create(User newUser)
{
QueryRunner run = new QueryRunner(dataSource);
try
{
run.update("INSERT INTO User (name, age) " +
"VALUES (?, ?)", newUser.getName(), newUser.getAge());
}
catch (SQLException ex)
{
Log.logException(ex);
return false;
}
return true;
}
protected User Read(int userId)
{
try
{
User user = run.query("SELECT * FROM User WHERE userId = ? ", userId);
return user;
}
catch (SQLException ex)
{
Log.logException(ex);
return null;
}
}
protected update(User user)
{
... perform database query etc
}
protected delete(int userId)
{
... perform database query etc
}
看来我能为你的问题提供一些简单的建议 (一) 不要像您正在做的那样管理DAO内部的查询,而是创建一个工厂类,该类具有满足您需要的查询列表 像 这将从DAO代码中分离查询,并使其更易于管理 (二) 实现通用DAO
3) 正如您前面提到的,使用ORM可以帮助您将bean绑定到数据库和更多功能 使用DBUtils,您已经抽象出了许多样板代码。剩下的主要工作是实体之间的差异:正确的sql语句、将实体对象转换为更新参数,以及使用SELECT和异常处理将实体对象转换为更新参数 不幸的是,要创建一个对这些剩余任务足够灵活的通用抽象并不容易。这就是ORM映射器的全部内容。我仍然建议调查其中一个。如果您坚持使用JPAAPI,那么您仍然处于标准领域,能够更轻松地切换ORM提供程序(尽管总是存在一些耦合)。 SpringData的存储库抽象给我留下了深刻的印象。在simple用例中,它们为您提供零代码DAO。如果您已经在使用Spring,并且只想持久化您的对象模型,那么您肯定应该研究它
或者,我也有一些很好的经验。它还可以基于模式中的表创建DTO和相应的DAO。与ORM映射器相比,它更接近关系模式,这可能是一个优点,也可能是一个缺点。您问我如何使用模板方法来实现这一点。下面是一个示例,您可以这样做:
public class AbstractDAO<T> {
private String table;
private String id_field;
public AbstractDAO(String table, String id_field){
this.table = table;
...
}
public T read(int id){
try
{
T user = run.query("SELECT * FROM "+ table + " WHERE "+id_field +" = ? ", id);
return user;
}
catch (SQLException ex)
{
Log.logException(ex);
return null;
}
}
难看,不安全,但可以传播想法。mybatis允许您以hashmap的形式返回结果类型:
选择managerName,计数(报告对象)作为计数
经理/雇员
按经理姓名分组;
因此,您可以在这样的工作流中有效地写出:
1) 开发接口
2a)使用mybatis注释定义所需的查询或
2b)将接口链接到xml并编写查询
请注意,这不会涉及任何DAO和上面提到的其他样板文件,模板方法不起作用,因为…?您是指Spring JDBC模板吗?不,我是指模板方法模式
public class AbstractDAO<T> {
private String table;
private String id_field;
public AbstractDAO(String table, String id_field){
this.table = table;
...
}
public T read(int id){
try
{
T user = run.query("SELECT * FROM "+ table + " WHERE "+id_field +" = ? ", id);
return user;
}
catch (SQLException ex)
{
Log.logException(ex);
return null;
}
}
public boolean Create(T user){
QueryRunner run = new QueryRunner(dataSource);
try
{
run.update("INSERT INTO "+table+ getFields() +
"VALUES " + getParameters(user));
}
catch (SQLException ex)
{
Log.logException(ex);
return false;
}
return true;
}
protected abstract String getFields();
protected abstract String getParameters(T user);