没有找到能够从类型 [java.lang.String] 转换为类型 [@Autowired @ManyToOne @JoinColumn com.papertrue.country.Country]

Posted

技术标签:

【中文标题】没有找到能够从类型 [java.lang.String] 转换为类型 [@Autowired @ManyToOne @JoinColumn com.papertrue.country.Country] 的转换器【英文标题】:No converter found capable of converting from type [java.lang.String] to type [@Autowired @ManyToOne @JoinColumn com.papertrue.country.Country] 【发布时间】:2020-11-05 05:24:13 【问题描述】:

所以我对 JPA 还是很陌生,在将一个对象映射到另一个对象时遇到了困难。这是我的用户实体:

package com.papertrue.user;

import com.papertrue.country.Country;
import com.papertrue.currency.Currency;

@Entity
@ConfigurationProperties("user")
@Table(name = "users")
public class User 

    @Id
    @Column(name = "id")
    private String userId;

    private String name;

    @Column(name = "phone_ext")
    private String phoneExt;

    @Column(name = "phone_no")
    private String phoneNo;

    private String email;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "country")
    private Country country;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "currency")
    private Currency currency;

    @Column(name = "fb_id")
    private String facebookId;

    @Column(name = "google_id")
    private String googleId;

    @Column(name = "current_balance")
    private int currentBalance;

    @Column(name = "is_enabled")
    private boolean isEnabled;

    @Column(name = "free_sample_used")
    private boolean isfreeSampleUsed;

    @Column(name = "client_id")
    private String clientId;


我的国家实体:

package com.papertrue.country;

import com.papertrue.currency.Currency;

@Entity
@ConfigurationProperties("country")
@Table(name = "countries")
public class Country 

    @Id
    private String code;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "currency")
    private Currency currency;

    @Column(name = "isd_ext")
    private String ISDExt;

    @Enumerated(EnumType.STRING)
    private transient Region region;

还有我的货币实体:

package com.papertrue.currency;

@Entity
@ConfigurationProperties("currency")
@Table(name = "currencies")
public class Currency 

    @Id
    private String code;

    private String symbol;

    private String name;

    private int multiplier;

    @Column(name = "minVal")
    private int minValue;


所以当我在 Country 对象中映射 Currency 时它可以工作,但是当我对 User 和 Country 做同样的事情时它就不行了。我收到org.springframework.core.convert.ConverterNotFoundException。这是错误:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132) ~[spring-test-5.3.0.jar:5.3.0]
Caused by: org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'user-com.papertrue.user.User': Could not bind properties to 'User' : prefix=user, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'user.country' to com.papertrue.country.Country
    ... 70 common frames omitted
Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'user.country' to com.papertrue.country.Country
    ... 89 common frames omitted
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [@javax.persistence.ManyToOne @javax.persistence.JoinColumn com.papertrue.country.Country]
    ... 105 common frames omitted

这是在我运行测试时发生的:

package com.papertrue;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;

import com.papertrue.exceptions.PaperTrueUserNotFoundException;
import com.papertrue.user.UserService;

@SpringBootTest
public class UserServiceTest 

    @Autowired
    private UserService userService;

    @Test
    public void contextLoads() 
        // Testing getEmailInstance
        System.out.println("====== getEmailInstance() ======");
        try 
            System.out.println(userService.getEmailInstance("text@papertrue.com").getName());
         catch (PaperTrueUserNotFoundException e) 
            e.printStackTrace();
        

    

    @SpringBootApplication
    static class TestConfiguration 
    


UserService 服务:

package com.papertrue.user;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import com.papertrue.exceptions.PaperTrueUserNotFoundException;

@Service
@EnableConfigurationProperties(User.class)
public class UserService 

    @Autowired
    private UserRepository userRepository;

    /**
     * Returns user whose email matches to parameter email's value.
     * 
     * @param email
     * @return
     * @throws PaperTrueUserNotFoundException
     */
    public User getEmailInstance(String email) throws PaperTrueUserNotFoundException 

        Optional<User> optional = userRepository.findByEmail(email);

        if (optional.isPresent()) 
            return optional.get();
        

        throw new PaperTrueUserNotFoundException("User Not Found");
    


以及供参考的存储库:

package com.papertrue.user;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, String> 

    Optional<User> findByEmail(String email);

【问题讨论】:

【参考方案1】:

异常告诉您它无法按照@ConfigurationProperties 的建议设置配置属性。因为对于国家/地区,它具有 String 值(可能在 application.properties 中)但需要 Country 并且没有转换器。

这就引出了一个问题:“你想用@ConfigurationProperties 注释来达到什么目的?”

在 JPA 实体上使用它至少是非正统的,因为 bean 和实体通常是两个非常不同的东西。

所以要么你应该删除@ConfigurationProperties 注释 或按此处所述注册自定义转换器: https://www.logicbig.com/tutorials/spring-framework/spring-boot/custom-configuration-properties-binding.html

【讨论】:

这是一个库项目,我将把这个项目导入另一个项目,因此 @ConfigurationProperties 注释,当我删除它时,我得到 java.lang.IllegalStateException: No ConfigurationProperties annotation found on 'com.papertrue.country.Country'. 我不明白这如何解释@ConfigurationProperties的目的 我按照这篇文章创建了库项目:spring.io/guides/gs/multi-module/#_create_the_library_project,它说,要使其在标准 Spring Boot 成语中可配置(使用 application.properties),您还可以添加一个@ConfigurationProperties 类。如果我删除它,应用程序会抛出异常。 这适用于配置或 bean,而不适用于实体。实体不像 bean 那样被 Spring 实例化。

以上是关于没有找到能够从类型 [java.lang.String] 转换为类型 [@Autowired @ManyToOne @JoinColumn com.papertrue.country.Country]的主要内容,如果未能解决你的问题,请参考以下文章

@AspectJ support (good)

没有找到能够从类型转换为类型的转换器

没有找到能够从类型 [java.lang.String] 转换为类型 [@Autowired @ManyToOne @JoinColumn com.papertrue.country.Country]

没有找到能够从 [java.lang.String] 类型转换为 [org.springframework.data.solr.core.geo.Point] 类型的转换器

没有找到能够从 AbstractJPAQuery 转换为 DTO 的转换器

Jackson ObjectMapper 无法反序列化 POJO,抛出异常:没有找到适合类型 [...] 的构造函数:无法从 JSON 对象实例化