Spring 数据 JDBC:DataRetrievalFailureException:无法将 [oracle.sql.ROWID] 转换为 [java.lang.Number]
Spring Data JDBC: DataRetrievalFailureException : Unable to cast [oracle.sql.ROWID] to [java.lang.Number]
我是 Spring 数据 JDBC 的新手,我正在努力创建一个简单的 Dto 并将其持久保存在数据库中。
我正在使用 Spring-Boot 2.1。1.RELEASE 和 Oracle 12 数据库。
UserDto
@Table(value="USERS_T")
public class UserDto extends PersistableDto {
@Id
@Column(value="USR_USERNAME")
private String userName;
@Column(value="USR_FIRSTNAME")
private String firstName;
@Column(value="USR_LASTNAME")
private String lastName;
.....
}
UserDao
@Repository
public interface UserDao extends CrudRepository<UserDto, String> {
@Query("SELECT * FROM USERS_T u WHERE u.USR_USERNAME = :userName")
UserDto findByUserName(@Param("userName") String userName);
}
我只是想像这样将它保存在数据库中
public String createUser() {
UserDto userDto = new UserDto().setUserName("mapss@sapot.wrong.email.pt").setPassword("superpass").setUserType("Guest").setActive(true);
logger.info(String.format("Creating user: " + userDto));
userDto.setNew(true);
UserDto persistedUser = userDao.save(userDto);
logger.info(String.format("Persisted user: " + persistedUser));
return "Ending of create user operation";
}
我遇到了这个异常。
org.springframework.dao.DataRetrievalFailureException: The generated key is not of a supported numeric type. Unable to cast [oracle.sql.ROWID] to [java.lang.Number]
at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:79) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.data.jdbc.core.DefaultDataAccessStrategy.getIdFromHolder(DefaultDataAccessStrategy.java:323) ~[spring-data-jdbc-1.0.3.RELEASE.jar:1.0.3.RELEASE]
我相信这在某种程度上与@Id 是一个字符串这一事实有关。
有人可以帮助我了解我做错了什么吗?为什么会有这种行为。在规范中,我没有看到对 Id 类型的限制。这是和Oracle集成的问题吗?我该如何解决这个问题?
谢谢大家的帮助。
我认为您需要在您的实体中声明 USR_ID 字段和相应的序列
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXXX")
@SequenceGenerator(sequenceName = "YYYY", allocationSize = 1, name = "XXXX")
Long USR_ID;
遗憾的是,Oracle 尚未得到完全支持。
an issue open for creating integration tests for Oracle and the accompanying PR 已经解决了一些问题,但肯定不是全部。
这里的主要问题是 Oracle 在生成密钥方面做了一些有趣的事情。我看到以下选项
a) 不要在数据库端使用密钥生成。 DATAJDBC-282 让这更舒服。但到目前为止它只在 SNAPSHOT 版本中。
b) 不要使用 Oracle。我们目前使用 MySql、Postgres、H2、HSQLDB 和 MariaDb
进行测试
c) 看一下上面提到的 PR,看看你是否可以修补它足以工作。
我知道这些选项不是很令人满意。
挑战在于开源项目很难与 Oracle 进行集成测试,因为即使从 public CI 构建下载合法的 Oracle JDBC 驱动程序也是一场噩梦,让单独一个数据库。
我们正在讨论情况时,一位同事给我发了这张图片:
但我们不放弃,适当的支持会添加。
我遇到了同样的问题,当 PR 被包含在下一个 Spring 数据 JDBC 版本中时,我们可以将以下解决方法与 Spring AOP 一起使用,它不是 "perfect" 但对我们来说足够了,直到根本问题得到解决:
@Around("execution(public * my-app-pacakage.repository.*.save(..))")
public Object aspectController(ProceedingJoinPoint jp) throws Throwable {
try {
return jp.proceed();
} catch (DbActionExecutionException e) {
if (e.getCause() instanceof DataRetrievalFailureException) {
return jp.getArgs()[0];
}
return e;
} catch(Throwable e) {
throw e;
}
}
我是 Spring 数据 JDBC 的新手,我正在努力创建一个简单的 Dto 并将其持久保存在数据库中。
我正在使用 Spring-Boot 2.1。1.RELEASE 和 Oracle 12 数据库。
UserDto
@Table(value="USERS_T")
public class UserDto extends PersistableDto {
@Id
@Column(value="USR_USERNAME")
private String userName;
@Column(value="USR_FIRSTNAME")
private String firstName;
@Column(value="USR_LASTNAME")
private String lastName;
.....
}
UserDao
@Repository
public interface UserDao extends CrudRepository<UserDto, String> {
@Query("SELECT * FROM USERS_T u WHERE u.USR_USERNAME = :userName")
UserDto findByUserName(@Param("userName") String userName);
}
我只是想像这样将它保存在数据库中
public String createUser() {
UserDto userDto = new UserDto().setUserName("mapss@sapot.wrong.email.pt").setPassword("superpass").setUserType("Guest").setActive(true);
logger.info(String.format("Creating user: " + userDto));
userDto.setNew(true);
UserDto persistedUser = userDao.save(userDto);
logger.info(String.format("Persisted user: " + persistedUser));
return "Ending of create user operation";
}
我遇到了这个异常。
org.springframework.dao.DataRetrievalFailureException: The generated key is not of a supported numeric type. Unable to cast [oracle.sql.ROWID] to [java.lang.Number]
at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:79) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.data.jdbc.core.DefaultDataAccessStrategy.getIdFromHolder(DefaultDataAccessStrategy.java:323) ~[spring-data-jdbc-1.0.3.RELEASE.jar:1.0.3.RELEASE]
我相信这在某种程度上与@Id 是一个字符串这一事实有关。
有人可以帮助我了解我做错了什么吗?为什么会有这种行为。在规范中,我没有看到对 Id 类型的限制。这是和Oracle集成的问题吗?我该如何解决这个问题?
谢谢大家的帮助。
我认为您需要在您的实体中声明 USR_ID 字段和相应的序列
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXXX")
@SequenceGenerator(sequenceName = "YYYY", allocationSize = 1, name = "XXXX")
Long USR_ID;
遗憾的是,Oracle 尚未得到完全支持。 an issue open for creating integration tests for Oracle and the accompanying PR 已经解决了一些问题,但肯定不是全部。
这里的主要问题是 Oracle 在生成密钥方面做了一些有趣的事情。我看到以下选项
a) 不要在数据库端使用密钥生成。 DATAJDBC-282 让这更舒服。但到目前为止它只在 SNAPSHOT 版本中。
b) 不要使用 Oracle。我们目前使用 MySql、Postgres、H2、HSQLDB 和 MariaDb
进行测试c) 看一下上面提到的 PR,看看你是否可以修补它足以工作。
我知道这些选项不是很令人满意。 挑战在于开源项目很难与 Oracle 进行集成测试,因为即使从 public CI 构建下载合法的 Oracle JDBC 驱动程序也是一场噩梦,让单独一个数据库。
我们正在讨论情况时,一位同事给我发了这张图片:
但我们不放弃,适当的支持会添加。
我遇到了同样的问题,当 PR 被包含在下一个 Spring 数据 JDBC 版本中时,我们可以将以下解决方法与 Spring AOP 一起使用,它不是 "perfect" 但对我们来说足够了,直到根本问题得到解决:
@Around("execution(public * my-app-pacakage.repository.*.save(..))")
public Object aspectController(ProceedingJoinPoint jp) throws Throwable {
try {
return jp.proceed();
} catch (DbActionExecutionException e) {
if (e.getCause() instanceof DataRetrievalFailureException) {
return jp.getArgs()[0];
}
return e;
} catch(Throwable e) {
throw e;
}
}