Ausgabe
Ich habe dieses Problem beim Testen – bereitgestellte ID des falschen Typs für die Klassecom.myapp.ibank.domain.Customer. Expected: class java.lang.Long, got class java.lang.String
Und ich kann ehrlich gesagt nicht herausfinden, warum ich das habe und was tatsächlich passiert. Wenn ich es normal verwende, z. B. auf einem lokalen Kater laufe und es über einen Controller und dann einen Dienst speichere, funktioniert es einwandfrei. Keine Fehler. Dieses Verhalten ergibt für mich keinen Sinn.
Ich verwende JPA 2.1 mit Hibernate als Anbieter.
Hier ist Testcode:
@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);
}
}
Meine Kundeneinheit (Kurzversion):
@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;
}
Und mein 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);
}
}
Was übersehe ich, oder ist das ein allgemeiner Fehler mit dem Ruhezustand, der sich nicht vermeiden lässt? Ich habe irgendwo gelesen, dass dies ein typischer Fehler ist.
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$1.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$1.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$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.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$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.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.access$2000(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
Kundenservice Impl:
@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);
}
}
Lösung
Ihre Methode ist definiert als
return em.find(Customer.class, Name);
EntityManager.find()
nimmt die ID einer Entität und gibt die Entität zurück, die diese ID hat. Die ID des Kunden ist ein Long. Es ist nicht der Name. Sie benötigen eine Abfrage zum Implementieren von findByName()
.
Beantwortet von – JB Nizet
Antwort geprüft von – Katrina (FixError Volunteer)