Java 在数据访问层中使用同步
假设我们正在开发一个类,该类实现了简单的CRUD操作来处理DB。此类还维护缓存以提高性能Java 在数据访问层中使用同步,java,performance,caching,synchronization,data-access-layer,Java,Performance,Caching,Synchronization,Data Access Layer,假设我们正在开发一个类,该类实现了简单的CRUD操作来处理DB。此类还维护缓存以提高性能 public class FooTableGateway { Map<Integer, Foo> id2foo = new HashMap<Integer, Foo> (); public void getFoo (int id) { if (id2foo.containsKey (id) { return id2foo.get (id);
public class FooTableGateway {
Map<Integer, Foo> id2foo = new HashMap<Integer, Foo> ();
public void getFoo (int id) {
if (id2foo.containsKey (id) {
return id2foo.get (id);
}
String query = "select ...";
Connection cn = null;
Statement st = null;
ResultSet rs = null;
try {
cn = DBUtils.getConnection ();
st = cn.createStatement ();
rs = st.executeQuery (query);
if (!rs.next ()) {
return null;
}
Foo foo = new Foo (rs.getString (1)...);
id2foo.put (id, foo);
return foo;
} catch (SQLException e) {
..
} finally {
..
}
}
public boolean addFoo (Foo foo) {
if (id2foo.values ().contains (foo) {
return false;
}
String query = "insert into ...";
Connection cn = null;
Statement st = null;
ResultSet rs = null;
try {
cn = DBUtils.getConnection ();
st = cn.createStatement ();
int num = st.executeUpdate (query.toString (),
Statement.RETURN_GENERATED_KEYS);
rs = st.getGeneratedKeys ();
rs.next ();
foo.setId (rs.getInt (1);
id2foo.put (foo.getId (), foo);
return true;
} catch (SQLException e) {
..
return false;
} finally {
..
}
}
public void updateFoo (Foo foo) {
//something similar
..
}
public boolean deleteFoo (int id) {
//something similar
..
}
}
公共类FooTableGateway{
Map id2foo=newhashmap();
公共void getFoo(int-id){
if(id2foo.containsKey(id){
返回id2foo.get(id);
}
字符串查询=“选择…”;
连接cn=null;
语句st=null;
结果集rs=null;
试一试{
cn=DBUtils.getConnection();
st=cn.createStatement();
rs=st.executeQuery(查询);
如果(!rs.next()){
返回null;
}
Foo-Foo=新的Foo(rs.getString(1)…);
id2foo.put(id,foo);
返回foo;
}捕获(SQLE异常){
..
}最后{
..
}
}
公共布尔addFoo(Foo-Foo){
if(id2foo.values().contains)(foo){
返回false;
}
字符串查询=“插入…”;
连接cn=null;
语句st=null;
结果集rs=null;
试一试{
cn=DBUtils.getConnection();
st=cn.createStatement();
int num=st.executeUpdate(query.toString(),
语句。返回\u生成的\u键);
rs=st.getGeneratedKeys();
rs.next();
foo.setId(rs.getInt(1);
id2foo.put(foo.getId(),foo);
返回true;
}捕获(SQLE异常){
..
返回false;
}最后{
..
}
}
公共void updateFoo(Foo-Foo){
//类似的东西
..
}
公共布尔deleteFoo(int-id){
//类似的东西
..
}
}
问题是:应该同步哪部分代码?(当然,我们正在开发web应用程序)。
如果我要同步对缓存集合的所有调用,那么我甚至不确定使用缓存是否会提高性能。哇……对于一个方法来说,这是很多代码。我真的建议将其分解为方法和对象,一次处理一件事 在上面给出的代码中,您应该在读、写和删除时同步缓存集合;这将锁定缓存,因此无法并行读取
编写一个高性能的线程安全缓存并不容易(特别是如果您现在或将来需要将其集群化的话)。您应该看看现有的缓存,如EHCache()或JBoss cache().哇……对于一个方法来说,代码太多了。我真的建议将它分解为方法和对象,一次处理一件事情 在上面给出的代码中,您应该在读、写和删除时同步缓存集合;这将锁定缓存,因此无法并行读取
编写一个高性能的线程安全缓存并不容易(特别是如果您现在或将来需要对其进行集群化的话)。您应该仔细看看现有的缓存,如EHCache()或JBoss cache()。编写的这段代码有太多问题 我认为DAO不应该与获取到数据库的连接有任何关系;它应该传入或注入到类中。DAO无法知道它是否正在更大的事务上下文中使用。应该使用一个单独的服务层,其方法对应于了解工作单元的用例负责获取连接、设置事务和隔离、封送DAO和业务实体以完成用例、提交或回滚事务以及清理资源 在这里,你有很多事情要做:持久性、缓存等等。如果你能开始剥离其中一些责任,把它们放到别处,你的生活会更好。我认为你的网关做得太多了 更新: 你扔到你的类中的映射告诉我这是一个巨大的错误。我没有看到任何软引用来帮助垃圾收集器。我没有看到任何努力来限制缓存的大小或更新值。这是一种自找麻烦的方法。编写缓存是一项巨大的努力。如果你不相信eve me,下载EhCache的源代码,并将其与您的地图进行比较。这不是小事 声明性事务没有逻辑——这是另一个巨大的错误 恕我直言,我会重新考虑这个实施方案
更好的建议是学习Spring和/或Hibernate。编写的代码有太多问题 我认为DAO不应该与获取到数据库的连接有任何关系;它应该传入或注入到类中。DAO无法知道它是否正在更大的事务上下文中使用。应该使用一个单独的服务层,其方法对应于了解工作单元的用例负责获取连接、设置事务和隔离、封送DAO和业务实体以完成用例、提交或回滚事务以及清理资源 在这里,你有很多事情要做:持久性、缓存等等。如果你能开始剥离其中一些责任,把它们放到别处,你的生活会更好。我认为你的网关做得太多了 更新: 你扔到你的类中的映射告诉我这是一个巨大的错误。我没有看到任何软引用来帮助垃圾收集器。我没有看到任何努力来限制缓存的大小或更新值。这是一种自找麻烦的方法。编写缓存是一项巨大的努力。如果你不相信eve me,下载EhCache的源代码,并将其与您的地图进行比较。这不是小事 声明性事务没有逻辑——这是另一个巨大的错误 恕我直言,我会侦察的
if (id2foo.containsKey (id) {
return id2foo.get (id);
}
id2foo.put (id, foo);
Map<Integer, Foo> id2foo = new HashMap<Integer, Foo> ();