MappingException:检测到不明确的字段映射

时间:2017-09-08 16:20:26

标签: spring-data-mongodb spring-mongodb

使用Spring boot 1.5.6.RELEASE。

我有以下mongo文档基类:

@Document(collection="validation_commercial")
public abstract class Tier {
    @Id
    private String id;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private Date created;
    @Field("tran")
    private Tran tran;

    public Tier() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Tran getTran() {
        return tran;
    }

    public void setTran(Tran tran) {
        this.tran = tran;
    }
}

然后扩展:

public class Tier1 extends Tier {

    @Field("tier1")
    private Tier1Programs tier1;

    public Tier1() {
        this.tier1 = new Tier1Programs();
    }

    public Tier1Programs getTier1() {
        return tier1;
    }

    public void setTier1(Tier1Programs tier1) {
        this.tier1 = tier1;
    }
}

反过来又扩展了:

public class Tier2 extends Tier1 {

    @Field("tier2")
    private Tier2Programs tier2;

    public Tier2() {
        this.tier2 = new Tier2Programs();
    }

    public Tier2Programs getTier2() {
        return tier2;
    }

    public void setTier2(Tier2Programs tier2) {
        this.tier2 = tier2;
    }
}

有一个Tier1 Supervisor(Spring Boot Application)在MongoRepository接口中使用Tier1类:

public interface Tier1Repository extends MongoRepository<Tier1,String>{}

用于检索和保存 - 没问题。

然后我有一个使用Tier1存储库的Tier2 Supervisor(Spring Boot应用程序)(用于检索Tier1文档和用于保存Tier2文档的Tier2存储库:

@Repository("tier1Repository")
public interface Tier1Repository extends MongoRepository<Tier1,String>{}

@Repository("tier2Repository")
public interface Tier2Repository extends MongoRepository<Tier2,String>{}

我的服务是:

@Service
public class TierService {
    @Qualifier("tier1Repository")
    @Autowired
    private final Tier1Repository tier1Repository;
    @Qualifier("tier2Repository")
    @Autowired
    private final Tier2Repository tier2Repository;

    public TierService(@Qualifier("tier1Repository") Tier1Repository tier1Repository, @Qualifier("tier2Repository") Tier2Repository tier2Repository) {
        this.tier1Repository = tier1Repository;
        this.tier2Repository = tier2Repository;
    }

    public Tier1 findOne(String id) {
        return tier1Repository.findOne(id);
    }

    public void SaveTier(Tier2 tier) {
        tier2Repository.save(tier);
    }

    public Tier1Repository getTier1Repository() {
        return tier1Repository;
    }

    public Tier2Repository getTier2Repository() {
        return tier2Repository;
    }
}

最后是app:

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,
    DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class})
@Configuration
@ComponentScan(basePackages = {"com.k12commercial.tier2supervisor"})
@ImportResource("classpath:application-context.xml")
public class Application implements CommandLineRunner {

    @Autowired
    private IReceiver raBidNetPriceReceiver;

    @Autowired
    private UdyDataSourceFactory udyDSRegistry;

    public static void main(String[] args) throws InterruptedException {
        try {
            SpringApplication.run(Application.class, args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }    

    @Override
    public void run(String... args) throws Exception {
        raBidNetPriceReceiver.processTierMessages();
        exit(0);
    }
}

当我从命令行运行Tier2 Supervisor时,出现以下错误:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'tierService' defined in URL [jar:file:/opt/java-commandline/tier2supervisor-1.0.jar!/BOOT-INF/classes!/com/k12commercial/tier2supervisor/service/TierService.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tier2Repository': Invocation of init method failed; nested exception is org.springframework.data.mapping.model.MappingException: Ambiguous field mapping detected! Both private final java.lang.reflect.Type org.springframework.data.util.TypeDiscoverer.type and private final java.lang.Class org.springframework.data.util.ClassTypeInformation.type map to the same field name type! Disambiguate using @Field annotation!

我不确定问题是否是Tier2扩展Tier1(确实尝试将@Document标记放在Tier1和Tier2之上而没有变化)。我想我已经标记了相关领域,所以不了解消除歧义的必要性。我认为这个问题有2个存储库(Spring Boot不知道哪个存储器到DI)所以删除了Tier1Repository - 没有工作。尝试更好地限定存储库但仍然得到相同的错误。我制作了Tier1和Tier2 @Transient并删除了该消息,但也删除了mongo文档中的tier1部分 - 所以错误的更正。

认为这是一个注释修复但没有看到它......

请指教 - 谢谢。

1 个答案:

答案 0 :(得分:0)

对不起延迟(我被拉开去处理其他事情)并感谢那些回复的人。

问题是我在我的Tier级程序中有一个MongoTemplate,例如Spring Boot试图自动装配的Tim2Programs(子库)。

通过将Mongo(CRUD)要求移到主管级别(我还用一个MongoTemplate替换了存储库以简化)我删除了歧义。 (我也删除了服务类)。

代码包含在RaBidNetReciever类

    @Component
public class RaBidNetPriceReceiver extends BaseReceiver implements IReceiver, ApplicationEventPublisherAware {
    private static final Logger LOGGER = LoggerFactory.getLogger(RaBidNetPriceReceiver.class);
    private final RabbitTemplate raBidNetPriceRabbitTemplate;

    public RaBidNetPriceReceiver(MongoTemplate mongoTemplate, RabbitTemplate raBidNetPriceRabbitTemplate) {
    super(mongoTemplate);
    this.raBidNetPriceRabbitTemplate = raBidNetPriceRabbitTemplate;
    }

    @Transactional
    public void processTierMessages() {
    try {
        while (true) {
            gson = getGsonBuilder().create();
            byte[] body = (byte[]) raBidNetPriceRabbitTemplate.receiveAndConvert();
            if (body == null) {
                setFinished(true);
                break;
            }
            tier1Message = gson.fromJson(new String(body), Tier1Message.class);
            // document a 'Tier1' type so retrieve Tier1 first...
            Tier1 tier1 = mongoTemplate.findById(tier1Message.getId(), Tier1.class);

            Tier2Message tier2Message = new Tier2Message(tier1Message.getTran(), tier1Message.getId());
            Tier2Process tierProcess = getTierProcess(tier2Message.getTran().getK12ArchitectureId());

            Tier2 tier2 = new Tier2();
            tier2.setId(tier1.getId());
            tier2.setTier1Programs(tier1.getTier1Programs());
            tier2.setCreated(tier1.getCreated());
            tier2.setTran(tier1.getTran());

            tierProcess.setTier(tier2);
            tier2 = tier2.getTier2Programs().getRaBidNetPriceProgram().process(tierProcess);
            mongoTemplate.save(tier2);

            if (tier2.getTier2Programs().getRaBidNetPriceProgram().isFinished()) {
                // publish event
                publisher.publishEvent(new ProgramEvent(this, "FINISHED", tier2Message));
            }
        }

     } catch (Exception e) {
        LOGGER.error("id: " + tier1Message.getId() + " " + e.getMessage());
     }
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
    this.publisher = applicationEventPublisher;
    }
}

谢谢,