我正在从解释的世界转换齿轮,我试图复制我在传递中使用的模式,但在Java中取得了巨大的成功.
缺点是我正在制作一个自定义DAO(不使用Hibernate或类似的东西……最终处理不同的数据库引擎(SQL和NoSQL)将是通用的.为了突破我只是使用MySQL / Prepared Statementments .
我想基本上定义一个DataMapper对象,负责将记录的字段映射到数据库中的字段.我试图封装任何冗余逻辑,以实现将类型转换为数据库期望格式的实现细节.在DataMapper中,我试图利用枚举列出字段:
public abstract class AbstractDataMapper<X> {
public static abstract class Field<Y> {
protected String name;
public Field(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public abstract void setValue(PreparedStatement stmt, int parameterIndex, Y value)
throws SQLException;
public abstract Y getValue(ResultSet rset)
throws SQLException;
}
public static class IntegerField extends AbstractDataMapper.Field<Integer> {
public IntegerField(String name) {
super(name);
}
@Override
public void setValue(PreparedStatement stmt, int parameterIndex,
Integer value) throws SQLException {
stmt.setInt(parameterIndex, value.intValue());
}
@Override
public Integer getValue(ResultSet rset) throws SQLException {
return new Integer(rset.getInt(this.name));
}
}
}
public class UserDataMapper extends AbstractDataMapper<UserDataRecord>{
public static enum Field {
entryId(new AbstractDataMapper.IntegerField("entryid"));
AbstractDataMapper.Field<?> field = null;
Field(AbstractDataMapper.Field<?> field) {
this.field = field;
}
public AbstractDataMapper.Field<?> getField() {
return this.field;
}
public String getName() {
return this.field.getName();
}
}
显然,我试图将示例截断为有意义的部分.
用于执行此操作的客户端代码
public int insert(UserDataRecord user) {
...
final String query =
"INSERT INTO users SET "
+ UserDataMapper.Field.entryId.getName() + " = ? ";
stmt = conn.prepareStatement(query);
UserDataMapper.Field.entryId.getField()
.setValue(stmt, 1, user.getEntryId());
}
我遇到的问题是最后一行.我试图使用与entryId枚举关联的泛型对象来使用它的特殊setValue函数,该函数处理将Integer转换为正确的格式.我的IDE给了我以下错误:
AbstractDataMapper.Field类型中的方法setValue(PreparedStatement,int,capture#13-of?)不适用于参数(PreparedStatement,int,Integer).
我相信我可以进入一系列疯狂的类型转换……但在那时,它可能会更容易暴露翻译细节.
有关实现此功能或修改此模式的任何想法更好吗?
解决方法:
枚举不能是通用的,所以你的情况有问题.
一种更简单的铸造方式
public static enum Field {
public <T> AbstractDataMapper.Field<T> getField() {
return (AbstractDataMapper.Field<T>)this.field;
}
// usage
UserDataMapper.Field.entryId.<Integer>getField()
更大的问题是,在这里使用枚举有什么意义?使用一些静态公共最终字段会简单得多.
public class UserDataMapper extends AbstractDataMapper<UserDataRecord>{
public interface Fields {
IntegerField entryId = new IntegerField("entryid"));
----
final String query =
"INSERT INTO users SET "
+ UserDataMapper.Field.entryId.getName() + " = ? ";
stmt = conn.prepareStatement(query);
UserDataMapper.Field.entryId
.setValue(stmt, 1, user.getEntryId());