gpt4 book ai didi

spring - JAXBElement : providing codec (/converter? ) 对于类 java.lang.Class

转载 作者:行者123 更新时间:2023-12-02 03:03:31 26 4
gpt4 key购买 nike

我一直在评估采用 spring-data-mongodb project 。总而言之,我的目标是:

  1. 使用现有的 XML 模式文件生成 Java 类。

XML Schema Model

这里需要注意的是ExtensionType包含protected List<Object> any;允许它存储任何类的对象。就我而言,它位于名为 TSDModule_Name_HereModuleType 的类中,可以浏览 here

  • 使用 spring-data-mongodb 作为持久存储

    • 这是通过使用简单的 ProductDataRepository 来实现的。

      @RepositoryRestResource(collectionResourceRel = "product", path = "product")
      public interface ProductDataRepository extends MongoRepository<TSDProductDataType, String> {
      TSDProductDataType queryByGtin(@Param("gtin") String gtin);
      }
    • 但是,未编码的 TSDProductDataType 包含 JAXBElement,spring-data-mongodb 似乎无法自行处理并抛出 CodecConfigurationException org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.lang.Class.

  • 以下是错误的陈述:

    TSDProductDataType tsdProductDataType = jaxbElement.getValue();
    repository.save(tsdProductDataType);

    Output in Debugger

    我尝试使用 spring-data-mongodb 的转换器,如所解释的 here但是,我似乎遗漏了一些东西,因为异常(exception)是关于“编解码器”而不是“转换器”。

    感谢任何帮助。

    编辑:

    为 JAXBElement 添加转换器

    注意:适用于 org.springframework.boot::spring-boot-starter-parent 版本 1.5.6.RELEASE。随着版本 2.0.0.M3 的到来, hell 开始了

    看来我之前尝试添加转换器时错过了一些东西。因此,我如下添加它来进行测试:

    @Component
    @ReadingConverter
    public class JAXBElementReadConverter implements Converter<DBObject, JAXBElement> {
    //@Autowired
    //MongoConverter converter;

    @Override
    public JAXBElement convert(DBObject dbObject) {
    Class declaredType, scope;
    QName name = qNameFromString((String)dbObject.get("name"));
    Object rawValue = dbObject.get("value");
    try {
    declaredType = Class.forName((String)dbObject.get("declaredType"));
    } catch (ClassNotFoundException e) {
    if (rawValue.getClass().isArray()) declaredType = List.class;
    else declaredType = LinkedHashMap.class;
    }
    try {
    scope = Class.forName((String) dbObject.get("scope"));
    } catch (ClassNotFoundException e) {
    scope = JAXBElement.GlobalScope.class;
    }
    //Object value = rawValue instanceof DBObject ? converter.read(declaredType, (DBObject) rawValue) : rawValue;
    Object value = "TODO";
    return new JAXBElement(name, declaredType, scope, value);
    }

    QName qNameFromString(String s) {
    String[] parts = s.split("[{}]");
    if (parts.length > 2) return new QName(parts[1], parts[2], parts[0]);
    if (parts.length == 1) return new QName(parts[0]);
    return new QName("undef");
    }
    }


    @Component
    @WritingConverter
    public class JAXBElementWriteConverter implements Converter<JAXBElement, DBObject> {
    //@Autowired
    //MongoConverter converter;

    @Override
    public DBObject convert(JAXBElement jaxbElement) {
    DBObject dbObject = new BasicDBObject();
    dbObject.put("name", qNameToString(jaxbElement.getName()));
    dbObject.put("declaredType", jaxbElement.getDeclaredType().getName());
    dbObject.put("scope", jaxbElement.getScope().getCanonicalName());
    //dbObject.put("value", converter.convertToMongoType(jaxbElement.getValue()));
    dbObject.put("value", "TODO");
    dbObject.put("_class", JAXBElement.class.getName());
    return dbObject;
    }

    public String qNameToString(QName name) {
    if (name.getNamespaceURI() == XMLConstants.NULL_NS_URI) return name.getLocalPart();
    return name.getPrefix() + '{' + name.getNamespaceURI() + '}' + name.getLocalPart();
    }
    }


    @SpringBootApplication
    public class TsdApplication {

    public static void main(String[] args) {
    SpringApplication.run(TsdApplication.class, args);
    }

    @Bean
    public CustomConversions customConversions() {
    return new CustomConversions(Arrays.asList(
    new JAXBElementReadConverter(),
    new JAXBElementWriteConverter()
    ));
    }
    }

    到目前为止一切顺利。但是,我如何实例化 MongoConverter converter;MongoConverter是一个接口(interface),所以我想我需要一个遵循该接口(interface)的可实例化类。有什么建议吗?

    最佳答案

    我理解对方便性的渴望,能够在没有样板的情况下将现有域对象映射到数据库层,但即使您没有遇到 JAXB 类结构问题,我仍然建议不要使用它逐字。除非这是一个简单的一次性项目,否则您几乎肯定会遇到这样的情况:域模型需要更改,但持久数据需要保持现有状态。如果您只是直接保留数据,则没有在较新的域模式和较旧的持久数据模式之间进行转换的机制。持久数据方案的版本控制也是明智的。

    您发布的用于编写客户转换器的链接是实现此目标的一种方法,并且非常适合 Spring 生态系统。该方法还应该解决您遇到的问题(关于底层困惑的 JAXB 数据结构无法干净转换)。

    您无法使该方法发挥作用吗?确保您使用 @Component 加上自动类扫描或通过某些 Configuration 类手动将它们加载到 Spring 上下文中。

    编辑以解决您的编辑问题:

    将以下内容添加到每个转换器中:

    private final MongoConverter converter;

    public JAXBElement____Converter(MongoConverter converter) {
    this.converter = converter;
    }

    尝试将 bean 定义更改为:

    @Bean
    public CustomConversions customConversions(@Lazy MongoConverter converter) {
    return new CustomConversions(Arrays.asList(
    new JAXBElementReadConverter(converter),
    new JAXBElementWriteConverter(converter)
    ));
    }

    关于spring - JAXBElement : providing codec (/converter? ) 对于类 java.lang.Class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46023866/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com