Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何减少数据库访问层中的代码重复?_Java_Sql_Database_Generics_Dao - Fatal编程技术网

Java 如何减少数据库访问层中的代码重复?

Java 如何减少数据库访问层中的代码重复?,java,sql,database,generics,dao,Java,Sql,Database,Generics,Dao,我是Java新手,我正在尝试实现一个基本的数据库访问层。 我正在使用ApacheDbutils来减少JDBC样板代码,这非常有效 问题是,我的实现对数据库中的每个表使用一个单独的CRUD类,复制这么多功能感觉不好 这是一种可接受的设计吗?如果不是,我可以做些什么来减少代码重复? 我可以重构我的解决方案以某种方式使用泛型吗 我意识到我可以使用ORM(myBatis、Hibernate等)作为解决方案,但如果我能帮助的话,我想尝试使用DBUtils和普通JDBC 仅供澄清: 假设我有两张桌子 ---

我是Java新手,我正在尝试实现一个基本的数据库访问层。 我正在使用ApacheDbutils来减少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
}

看来我能为你的问题提供一些简单的建议

(一)

不要像您正在做的那样管理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);