2

我是 Spring Data JDBC 的新手,我正在努力创建一个简单的 Dto 并将其保留在数据库中。

我正在使用 Spring-Boot 2.1.1.RELEASE 和 Oracle 12 数据库。

用户Dto

@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; 
.....
}

用户道

@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集成的问题吗?我怎样才能解决这个问题?

感谢大家的帮助。

4

3 回答 3

2

不幸的是,Oracle 尚未得到完全支持。为 Oracle 创建集成测试存在一个问题,随附的 PR已经解决了一些问题,但肯定不是全部。

这里的主要问题是 Oracle 在生成密钥方面做了一些有趣的事情。我看到以下选项

a) 不要在数据库端使用密钥生成。DATAJDBC-282使这更加舒适。但到目前为止,它仅在 SNAPSHOT 版本中。

b) 不要使用 Oracle。我们目前使用 MySql、Postgres、H2、HSQLDB 和 MariaDb 进行测试

c) 看看上面提到的 PR,看看你是否可以修补它足以工作。

我知道这些选项不是很令人满意。挑战在于,开源项目很难与 Oracle 进行集成测试,因为即使从公共 CI 构建下载合法的 Oracle JDBC 驱动程序也是一场噩梦,更不用说数据库了。

当我们讨论这种情况时,一位同事给我发了这张图片:

在此处输入图像描述

但我们不放弃,适当的支持会增加。

于 2019-01-18T12:45:50.293 回答
1

我遇到了同样的问题,虽然 PR 包含在下一个 Spring Data JDBC 版本中,但我们可以在 Spring AOP 中使用以下解决方法,它不是“完美的”,但对我们来说已经足够了,直到根本问题得到解决:

@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;        
    }       
}
于 2019-02-04T17:14:10.703 回答
0

我认为您需要在您的实体中声明 USR_ID 字段和相应的序列

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXXX")
@SequenceGenerator(sequenceName = "YYYY", allocationSize = 1, name = "XXXX")
Long USR_ID;
于 2019-01-17T18:35:39.327 回答