java 测试时为类提供了错误类型的 ID

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32669889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 20:35:57  来源:igfitidea点击:

Provided id of the wrong type for class when testing

javaspringhibernatespring-mvcjpa

提问by Ru Ru

I have got this issue when testing- Provided id of the wrong type for class com.myapp.ibank.domain.Customer. Expected: class java.lang.Long, got class java.lang.String

我在测试时遇到了这个问题 - 为类提供了错误类型的 id com.myapp.ibank.domain.Customer. Expected: class java.lang.Long, got class java.lang.String

And I honestly cant figure out why I have got this and what is actually happening. When I use it normally, like running on a local tomcat and saving it through a controller and then service, it works just fine. No errors. This behaviour makes no sense to me.

老实说,我无法弄清楚为什么我会得到这个以及实际发生了什么。当我正常使用的时候,比如在本地tomcat上运行,通过控制器保存然后服务,就可以了。没有错误。这种行为对我来说毫无意义。

I am using JPA 2.1 with Hibernate as a provider.

我使用 JPA 2.1 和 Hibernate 作为提供程序。

Here is test code:

下面是测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextHierarchy({
        @ContextConfiguration(classes = RootConfig.class),
        @ContextConfiguration(classes = WebConfig.class)

})
@Transactional
public class AccountRepositoryTest {

    @Autowired
    private WebApplicationContext wac;
    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private CustomerService customerService;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();

        Customer cus = new Customer();
        cus.setFirstName("John");
        cus.setLastName("Smith");
        customerService.save(cus);
    }

    @Test
    public void testSaveAccount() {

        Account account = new Account();
        account.setCustomer(customerService.findByName("John"));
        account.setName();
        account.setDebitCard(new DebitCard((long) 2000));

        accountRepository.create(account);
    }

    @Test
    public void testSavePremiumAccount() {

        PremiumAccount premAccount = new PremiumAccount();
        premAccount.setCustomer(customerService.findByName("John"));
        premAccount.setName();
        premAccount.setDebitCard(new DebitCard((long) 6000));
        premAccount.setCreditCard(new CreditCard((long) 12000));

        accountRepository.create(premAccount);
    }

}

My Customer Entity (Short version):

我的客户实体(简短版本):

@Entity
@DynamicUpdate
@Table(name = "customer")
public class Customer implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "customer")
    //@JoinColumn(name="account_id", referencedColumnName="id")
    @Nullable
    @JsonManagedReference
    private List<Account> Accounts = new ArrayList<Account>();
    //private Address Address;


    public Customer() {
    }

    public Customer(String firstName, String lastName,  List<Account> accounts) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.Accounts = accounts;
    }

And my repo:

还有我的回购:

@Repository("customerRepository")
public class CustomerRepositoryImpl implements CustomerRepository {

    @PersistenceContext
    private EntityManager em;


    @Override
    @Transactional
    @NotNull
    public void save(Customer customer) {
        em.persist(customer);
        em.flush();
    }

    @Override
    public Customer findByName(String Name) {
    return em.find(Customer.class, Name);
    }
}

What do I miss, or is this a general bug with the hibernate that cant be avoided? I read somewhere that this is a typical bug.

我错过了什么,或者这是无法避免的休眠的一般错误?我在某处读到这是一个典型的错误。

Full Stack Trace:

全栈跟踪:

org.springframework.dao.InvalidDataAccessApiUsageException: Provided id of the wrong type for class com.ruruapps.ibank.domain.Customer. Expected: class java.lang.Long, got class java.lang.String; nested exception is java.lang.IllegalArgumentException: Provided id of the wrong type for class com.ruruapps.ibank.domain.Customer. Expected: class java.lang.Long, got class java.lang.String
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:381)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:157)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy45.findByName(Unknown Source)
    at com.ruruapps.ibank.service.CustomerServiceImpl.findByName(CustomerServiceImpl.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy48.findByName(Unknown Source)
    at com.ruruapps.ibank.AccountRepositoryTest.testSaveAccount(AccountRepositoryTest.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:72)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:81)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:216)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:82)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access
@Service("customerService")
@Transactional
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerRepository customerRepository;

    @Override
    public void save(Customer customer) {
        customerRepository.save(customer);
    }

    @Override
    public List<Customer> findAll() {
        return customerRepository.findAll();
    }

    @Override
    public Customer findById(Long id) {
        return customerRepository.findById(id);
    }

    @Override
    public Customer findByName(String Name) {
        return customerRepository.findByName(Name);
    }
}
0(ParentRunner.java:53) at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:60) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:67) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:162) at org.junit.runners.Suite.runChild(Suite.java:127) at org.junit.runners.Suite.runChild(Suite.java:26) at org.junit.runners.ParentRunner.run(ParentRunner.java:238) at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access
return em.find(Customer.class, Name);
0(ParentRunner.java:53) at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.junit.runner.JUnitCore.run(JUnitCore.java:160) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Caused by: java.lang.IllegalArgumentException: Provided id of the wrong type for class com.ruruapps.ibank.domain.Customer. Expected: class java.lang.Long, got class java.lang.String at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1135) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1068) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:291) at com.sun.proxy.$Proxy44.find(Unknown Source) at com.ruruapps.ibank.repository.CustomerRepositoryImpl.findByName(CustomerRepositoryImpl.java:47) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ... 59 more Caused by: org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.ruruapps.ibank.domain.Customer. Expected: class java.lang.Long, got class java.lang.String at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:134) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1106) at org.hibernate.internal.SessionImpl.access00(SessionImpl.java:176) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2587) at org.hibernate.internal.SessionImpl.get(SessionImpl.java:991) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1110) ... 75 more

Customer Service Impl:

客户服务实施:

##代码##

采纳答案by JB Nizet

Your method is defined as

您的方法定义为

##代码##

EntityManager.find()takes the ID of an entity, and returns the entity that has that ID. The ID of Customer is a Long. It's not the name. You need a query to implement findByName().

EntityManager.find()获取实体的 ID,并返回具有该 ID 的实体。客户的 ID 是一个 Long。这不是名字。您需要一个查询来实现findByName()

回答by Dejazmach

I faced this problem and the cause was that I didn't specify 'Name' as an ID(a primary key) in my model. As a result the parameter I passed as Id was being compared with the system generated Id (hjid) of that Customer object, and ended up not finding the object with that system generated ID (which is long in type). So it is necessary to explicitly specify the desired primary key in the model.

我遇到了这个问题,原因是我没有在模型中将“名称”指定为 ID(主键)。结果,我作为 Id 传递的参数与该 Customer 对象的系统生成的 Id (hjid) 进行了比较,最终找不到具有该系统生成的 ID(类型很长)的对象。所以有必要在模型中明确指定所需的主键。