Jdbi 和继承:条件映射?

如何解决Jdbi 和继承:条件映射?

我有一个名为 Tags 的表,它将“标签”存储为一行,而不管它们代表什么特定的子类。一些行代表 modbus 标签,一些 snmp,一些其他协议。从 Tag 继承的所有类都将它们的数据存储在这个表中,未使用的列只包含空值。

目前,我有 DAO 方法,例如 getAllModBusTags(),其中包含指令 mapToBean(ModBusTag.class)。最终,所有 Tag 的子类都从数据库获取(每个协议获取一个),然后添加到超类型 Tag 的 ArrayList 中。

我的问题是,jdbi 是否有一种简单的方法来执行行的条件映射,以便如果一行包含特定值,则将其映射到 ModBusTag.class,但如果一行包含不同的值,则它会映射到 SNMPTag .class 等等?

我的最终目标是有一个选择语句,从数据库获取每个标签,逐行自动映射到正确的 bean,然后将所有这些子类 bean 存储在超类型 Tag 的列表中。

>

单一类型的示例方法

@Override
public List<SNMPTag> getSNMPTags(){
    try(Handle handle = daoFactory.getDataSourceController().open()) {
        return handle.createquery("SELECT * FROM dbo.Tags WHERE Active = 1 AND Protocol = 'SNMP'")
                .mapToBean(SNMPTag.class)
                .list();
    }
    catch(Exception e){
        if(sysconfig.getVerbose()){ e.printstacktrace(); }
    }
    return null;
}

一些错误的伪代码来表明我想做什么:

@Override
public List<Tag> getAllTags(){
    try(Handle handle = daoFactory.getDataSourceController().open()) {
        return handle.createquery("SELECT * FROM dbo.Tags WHERE Active = 1")
        .mapRows(row -> row.Protocol.equals("SNMP").mapToBean(SNMPTag.class)
        .mapRows(row -> row.Protocol.equals("ModBus").mapToBean(ModBusTag.class)
        //etc
        .list();
    }
    catch(Exception e){
        if(sysconfig.getVerbose()){ e.printstacktrace(); }
    }
    return null;
}

解决方法

您可以使用带有一些自定义代码的 RowMapper 来实现您的需要,我们在我们的项目中成功地使用了这种方法。以下是此技术的简化一般示例:

public class PolymorphicRowMapper implements RowMapper<Parent> {

    @Override
    public Parent map(ResultSet rs,StatementContext ctx) throws SQLException {
        Type type = Type.valueOf(rs.getString("type"));
        if (type == Type.A) {
            return mapTo(rs,ctx,ChildA.class);
        } else if (type == Type.B) {
            return mapTo(rs,ChildB.class);
        }
        throw new IllegalStateException("Could not resolve mapping strategy for object");
    }

    private static <T extends Parent> T mapTo(
        ResultSet rs,StatementContext ctx,Class<T> targetClass
    ) throws SQLException {
        return ctx.getConfig().get(Mappers.class)
            .findFor(targetClass)
            .orElseThrow(() ->
                new NoSuchMapperException(String.format("No mapper registered for %s class",targetClass))
            )
            .map(rs,ctx);
    }

}

public static void main(String[] args) {
    var jdbi = Jdbi.create("...")
        .registerRowMapper(BeanMapper.factory(ChildA.class))
        .registerRowMapper(BeanMapper.factory(ChildB.class));
    try (Handle handle = jdbi.open()) {
        handle.createQuery("SELECT * FROM table")
            .map(new PolymorphicRowMapper());
    }
}

public enum Type {
    A,B
}

public abstract class Parent {
    final Type type;

    protected Parent(final Type type) {
        this.type = type;
    }
}

public class ChildA extends Parent {

    public ChildA() {
        super(Type.A);
    }

}

public class ChildB extends Parent {

    public ChildB() {
        super(Type.B);
    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?