JpaRepository 将自定义接口错误为 属性

JpaRepository mistakes custom interface as property

对于一般的springJpaRepository DAO(nospring-boot),如果接口扩展自定义接口,spring会出错接口方法作为对象的属性。

例如

interface ILocalDateTime {
  fun getLocalDateTime() : LocalDateTime
}

interface UserDaoCustom : ILocalDateTime {
    // query functions skipped
}

interface UserDao : JpaRepository<User, Long>, UserDaoCustom

class UserImpl : UserDaoCustom {

  @PersistenceContext
  private lateinit var em: EntityManager

  override fun getLocalDateTime(): LocalDateTime {
    return LocalDateTime.now()
  }

  // query functions skipped
}

这是一个简化的 UserDaoUserDaoCustom extends ILocalDateTime 其中包含一个方法 getLocalDateTime .

注意:localDateTime 不是 User 的字段。

在运行时,JpaRepository会将getLocalDateTime(或localDateTime?)误认为是User的字段,并抛出这样的异常:

Caused by: org.springframework.data.repository.query.QueryCreationException: 
Could not create query for public abstract java.time.LocalDateTime foo.ILocalDateTime.getLocalDateTime()! 
Reason: Failed to create query for method public abstract java.time.LocalDateTime foo.ILocalDateTime.getLocalDateTime()! 
No property getLocalDateTime found for type User!; 
nested exception is java.lang.IllegalArgumentException: 
Failed to create query for method public abstract java.time.LocalDateTime foo.ILocalDateTime.getLocalDateTime()! 
No property getLocalDateTime found for type User!

环境:

Kotlin 1.6.20
Spring 5.3.19
spring-data-jpa 2.5.11

如何解决这个问题? (能够或不能修改ILocalDateTime的代码)

谢谢。

我认为这是关于命名以及如何 Spring 获取存储库扩展的实现。

TLDR; 将您的实施名称从 UserImpl 更改为 UserDaoCustomImpl.

我检查了一个类似的设置,使用你的命名失败并出现完全相同的错误,但将其命名为“正确”使其按预期工作

public interface ILocalDateTime {
    LocalDateTime getLocalDateTime();
}

@Repository
public interface UserDao extends UserDaoCustom, JpaRepository<User, Long> {
}

public interface UserDaoCustom extends ILocalDateTime{
}

@Repository
public class UserDaoCustomImpl implements UserDaoCustom {
    @Override
    public LocalDateTime getLocalDateTime() {
        return LocalDateTime.now();
    }
}

和测试

@ExtendWith(SpringExtension.class)
@DataJpaTest
class UserRepositoryTest {
    @Autowired
    private UserDao userDao;

    @Test
    public void savesUser() {
        userDao.save(new User());
    }

    @Test
    public void bazzinga() {
        assert userDao.getLocalDateTime() != null;
        System.out.println("Bazzinga!"+userDao.getLocalDateTime());
    }


}

产量