有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使数据访问对象无阻塞?

我正在学习数据访问对象模式,它提供对数据源(如数据库)的访问This answer另一个问题提供了以下示例:

interface EmployeeDAO {
    List<Employee> findAll();
    List<Employee> findById();
    List<Employee> findByName();
    boolean insertEmployee(Employee employee);
    boolean updateEmployee(Employee employee);
    boolean deleteEmployee(Employee employee);
}

我在互联网上的其他答案和文章中看到了类似的例子。让我困惑的是,读取和写入数据库通常需要一段时间,在这种情况下,就我所知,这些例子(尤其是find...()的例子)并不实用。也就是说,在find...()调用期间阻塞可能不是期望的行为

我认为用void EmployeeFound(Employee employee)等方法创建一个侦听器接口(EmployeeDAO.Listener)是有意义的,但我很惊讶我以前没有在DAO示例中看到过这一点。我想知道我是否只是不了解数据访问对象和/或是否缺少一种更明显的方法


共 (2) 个答案

  1. # 1 楼答案

    在上面的接口中实现的方法将是简单的sql查询

    • “全部查找”将是“从表中选择”
    • 按id查找将是“select*from table where id=:id”(这是表的主键,并已索引)

    我在一个应用程序中工作,每天执行数百万条insert语句,我们不担心阻塞。如果您使用java,并且使用Spring框架,那么有一些库可以为您处理所有这些问题。查看java中的EntityManager和TransactionManager。坚持

  2. # 2 楼答案

    通常会采取多种不同的选择/方法:

    1. 阻塞就像您展示的API一样。这是一个非常简单的API,通过在多线程应用程序中调用API仍然可以实现并行性

    2. 在异步操作中接收/注册处理程序。这有时与阻塞API一起提供(实际上,可以通过生成后台线程,然后在最后调用处理程序,根据阻塞API实现)

    3. 返回一个未来的ListenableFuture对象,这使接口更符合Java风格(通过在返回类型位置返回数据),但表示最终结果,而不是立即可用的结果。未来可以用来阻止或不阻止

    我个人的建议是:

    interface EmployeeDatabase {
       interface StringWhereClause {
         ListQueryBuilder is(String value);
         ListQueryBuilder contains(String value);
         ListQueryBUilder matchesRegex(String regex);
       }
    
       interface IntWhereClause {
         ListQueryBuilder is(int value);
         ListQueryBuilder isInRange(int min, int max);
         ListQueryBuilder isGreaterThan(int value);
         ListQueryBUilder isLessThan(int value);
         ListQueryBuilder isGreaterThanOrEqualTo(int value);
         ListQueryBUilder isLessThanOrEqualTo(int value);
       }
       // ... matchers for other types of properties ...
    
       interface ListQueryBuilder {
          // Generic restrict methods
          StringWhereClause whereStringProperty(String propertyName);
          IntWhereClause whereIntProperty(String propertyName);
          // ...
    
          // Named restrict methods
          StringWhereClause whereName();
          StringWhereClause whereJobTitle();
          IntWhereClause whereEmployeeNumber();
          // ...
    
          ListQueryBuilder limit(long maximumSize);
          ListQueryBuilder offset(long index);
    
          ResultSet<Employee> fetch();
       }
    
       ListQueryBuilder list();
       ListenableFuture<Employee> getById(Key key);
       ListenableFuture<KeyOrError> add(Employee employee);
       ListenableFuture<Status> update(Key key, Employee employee);
       ListenableFuture<Status> delete(Key key);
    }
    

    与:

     interface ResultSet<T> {
        Iterable<T> asIterable();
        // ... other methods ...
     }
    
     interface KeyOrError {
        boolean isError();
        boolean isKey();
        Key getKey();
        Throwable getError();
     }
    
     interface Status {
       boolean isOk();
       boolean isError();
       Throwable getError();
       void verifyOk();
     }
    

    基本上,这个想法是,插入到数据库中会返回一个键对象(如果不成功,则返回一个错误)。此键可用于检索、删除或更新数据库中的条目。这些操作(add、update、delete和getById)都有一个结果,在这种情况下,使用ListenableFuture<T>而不是类型T;此future对象允许您阻止(通过对future对象调用.get())或异步检索该对象(通过注册一个回调,以便在结果就绪时调用)

    对于list-y操作,有许多不同的方法可以对列表进行筛选、再选择、排序等。为了防止各种不同重载的组合爆炸,我们使用builder pattern允许在多个组合中应用这些不同的限制。简而言之,构建器界面提供了一种方法,在调用fetch()之前,添加零个或多个选项(排序、筛选、限制等)以应用检索操作,从而执行列表查询并返回ResultSet。此操作返回一个ResultSet而不是一个ListenableFuture,因为结果不是一次全部返回的(例如,它们可能以流式方式从数据库返回);ResultSet实际上是一个接口,其行为与ListenableFuture类似,但用于项目列表(项目可能在不同时间准备就绪)。为了方便起见,重要的是要有一种方法可以轻松地迭代结果集的内容(例如,通过向结果集提供Iterable适配器);但是,您可能还想添加其他方法,允许您在ResultSet上执行其他类型的异步处理;例如,您可能需要一个ListenableFuture<T> reduce(T initialValue, ReduceFunction<T> reducer)来聚合结果集中的元素,并提供一个表示该结果最终完成的未来对象