代码之家  ›  专栏  ›  技术社区  ›  James P. PachinSV

DAO方法与同步

  •  8
  • James P. PachinSV  · 技术社区  · 14 年前

    以下是我目前在抽象DAO类中拥有的方法。如果存在并发调用,它们是安全的还是应该使用同步?我知道如果在方法的作用域之外有对属性的引用,应该使用同步,但是我不清楚应该如何使用外部资源来处理事情。

    public Connection getConnection() {
        // Call to singleton handling JDBC stuff
        return Database.getInstance().getCon();
    }
    
    public boolean isConnectionAvailable(){     
        if( getConnection() != null ){
            return true;
        }
    
        return false;
    }
    
    public PreparedStatement getPreparedStatement( String sqlStatement ){
        Connection connection = getConnection();
        PreparedStatement pS = null;
    
        if( connection != null ){
            try {
                pS = connection.prepareStatement( sqlStatement );
            } catch (SQLException e) {
                return null;
            }
        }
    
        return pS;
    }
    

    编辑:我可能会重新表述这个问题,以包含有关编写dao的信息,因为这是这里的重要内容。

    6 回复  |  直到 14 年前
        1
  •  13
  •   duffymo    14 年前

    我一点也不同意这种做法。

    首先,dao应该由拥有工作单元和事务的服务提供它们的连接信息。

    第四,准备好的声明应该只是内部执行的一部分。如果他们从你的刀里漏出来,你就做错了。

    第五,将事先准备好的语句从对象中传递出去,使得关闭和清理对象的责任远不明确。你的刀很快就会被资源泄漏致死。

    这里有一个通用DAO的接口。您会注意到,这都是CRUD操作,没有提到连接或来自的任何接口java.sql 包裹:

    package persistence;
    
    import java.io.Serializable;
    import java.util.List;
    
    public interface GenericDao<T, K extends Serializable>
    {
        T find(K id);
        List<T> find();
        List<T> find(T example);
        List<T> find(String queryName, String [] paramNames, Object [] bindValues);
    
        K save(T instance);
        void update(T instance);
        void delete(T instance);
    }
    

    你可以做很多事。这是一个更好的抽象。这个 T K 是主键。

        2
  •  3
  •   Bozho    14 年前

    getCon() 返回一个新的 Connection ThreadLocal 连接,那么你是安全的,没有必要使用 synchronized

    如果您将相同的连接返回给所有人,您可能仍会保存同步,因为连接中没有更改的状态(在当前代码中)。但你应该避免这种做法。请考虑使用连接池。

    只有

        3
  •  3
  •   Dave    14 年前

    JDBC连接类不能保证线程安全。如果你的Database.getInstance().getCon()方法总是返回相同的连接,那么您将遇到问题。但是,如果它使用的是一个池,那么每次调用getInstance().getCon()都会返回一个不同的连接,就可以了。

    也就是说,如果每次调用getCon()都返回不同的连接,那么如果希望两个Prepared语句调用使用相同的连接(和相同的事务),getPreparedStatement()将不起作用。

    我喜欢Spring的JDBCTemplate类作为DAO类的基础。

        4
  •  2
  •   Colin Hebert    14 年前

        5
  •  2
  •   Nathan Hughes    14 年前

    看看Spring是怎么做到的,他们已经搞清楚了所有这些东西,没有必要再发明了。查看与Spring的完整发行版捆绑在一起的petclinic示例代码,或者(对于非Spring方法)阅读Bauer/King Hibernate书籍中的DAO章节。

    当然DAO不应该负责获取数据库连接,因为您需要在同一事务中对多个DAO调用进行分组。Spring的做法是,服务层将其事务方法包装在拦截器中,拦截器从数据源提取连接并将其放入threadlocal变量中,DAOs可以在其中找到它。

    吃掉SQLException并返回null是不好的。正如duffymo指出的那样,让PreparedStatement被传递而不保证它会被关闭是非常糟糕的。而且,没有人应该再使用原始JDBC了,Ibatis或springjdbc是更好的选择。

        6
  •  0
  •   Satakshi Pandey    4 年前

    连接只是一个接口。它不是线程安全的。JDBC驱动程序也不是线程安全的。

        7
  •  -1
  •   Tushar Tarkas    14 年前