我是Java的新手,我正在尝试实现基本的数据库访问层。 我正在使用Apache DBUtils来减少JDBC样板代码,这非常有用。
问题是我的实现为我的数据库中的每个表使用一个单独的CRUD类,并且复制这么多功能感觉不对。
这是否是可接受的设计,如果不能,我该怎么做才能减少代码重复? 我可以重构我的解决方案以某种方式使用泛型吗?
我意识到我可以使用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
}
答案 0 :(得分:0)
看起来我可以为您的问题提供一些简单的建议。
1)
不要像你正在做的那样管理DAO中的查询,而是创建一个包含查询列表的工厂类。
像
class QueryFactory {
static String INSERT_BOOK = "BLAH";
static String DELETE_BOOK = "BLAH";
}
这会将查询与DAO代码分开,并使其更易于管理。
2)
实施通用DAO
http://www.codeproject.com/Articles/251166/The-Generic-DAO-pattern-in-Java-with-Spring-3-and
3)如上所述,使用ORM帮助自己将bean绑定到数据库以及更多功能。
答案 1 :(得分:0)
使用DBUtils已经抽象出了大量的样板代码。剩下的主要是实体之间不同的工作:正确的sql语句,将实体对象转换为UPDATE参数,反之亦然,使用SELECT,异常处理。
不幸的是,为这些剩余的任务创建足够灵活的通用抽象并不容易。这就是ORM地图制作者的全部意义所在。我仍然建议调查其中一个。如果您坚持使用JPA API,那么您仍然处于标准状态,并且能够更轻松地切换ORM提供程序(尽管总有一些耦合)。 SpringData的Repository抽象给我留下了深刻的印象。在简单用例中,他们为您提供零代码DAO。如果您已经在使用Spring,并且只想坚持您的对象模型,那么您一定要查看它。
或者我用jooq做了一些很好的经历。它还可以根据模式中的表创建DTO和相应的DAO。与ORM映射器相比,它更接近关系模式,这可能是一个优点或缺点。
答案 2 :(得分:0)
您问我将如何使用Template方法执行此操作。这是一个如何做到的例子:
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);
丑陋且不安全,但可以传达这个想法。
答案 3 :(得分:0)
mybatis允许您将结果类型作为hashmap返回:
<select id="mCount" resultType="hashmap">
select managerName, count(reportees) AS count
from mgr_employee
group by managerName;
</select>
所以你可以在这样的工作流程中有效地写出来: 1)开发界面 2a)使用mybatis批注定义所需的查询OR 2b)将接口链接到xml并编写查询
请注意,这不涉及任何DAO和其他涉及如上所述的模板