java - Spring转换器不转换自定义实体

标签 java spring hibernate spring-boot jpa

我正在尝试使用转换器注释来加密/解密 dbField,这是处理其他实体,其中查询的结果(在存储库上)是实体本身。在本例中,我返回自定义 POJO,而不是数据库实体,并且 dbField(私有(private)内容)未按应有的方式进行转换。也许我错过了一些东西。

信息正在数据库上加密,但我在服务上获取加密信息,因此它没有被解密。

我搜索了文档,但找不到有关自定义查询和转换器的任何内容。

下面您可以看到代码。我可以提供任何进一步的信息。感谢您抽出时间。

DbEntity

@Entity
public class History {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Convert(converter = CryptoConverter.class)    
    private String privateContent;

    // getters and setters omitted for clarity
}

转换器

@Converter
public class CryptoConverter implements AttributeConverter<String, String> {

    private static final String ALGORITHM = "AES/ECB/PKCS5Padding";
    private static final byte[] KEY = "BLABLAKEY".getBytes();

    @Override
    public String convertToDatabaseColumn(String clientData) {
        if(isBlank(clientData)){
            return clientData;
        }

        Key key = new SecretKeySpec(KEY, "AES");
        try {
            Cipher c = Cipher.getInstance(ALGORITHM);
            c.init(Cipher.ENCRYPT_MODE, key);
            return Base64.getEncoder().encodeToString(c.doFinal(clientData.getBytes()));
        } catch (Exception e) {
            throw new CryptoException(e);
        }
    }

    @Override
    public String convertToEntityAttribute(String dbData) {
        if(isBlank(dbData)){
            return dbData;
        }

        Key key = new SecretKeySpec(KEY, "AES");
        try {
            Cipher c = Cipher.getInstance(ALGORITHM);
            c.init(Cipher.DECRYPT_MODE, key);
            return new String(c.doFinal(Base64.getDecoder().decode(dbData)));
        } catch (Exception e) {
            throw new CryptoException(e);
        }
    }
}

存储库

@Repository
public interface HistoryRepository extends JpaRepository<History, Long> {

    @Query(value = "SELECT mh.id, mh.privateContent FROM history mh WHERE mh.account=:account")
    List<HistoryDB> getHistory(@Param("account") final Long account);

}

自定义 POJO

public interface HistoryDB {

    String getId();

    String getPrivateContent();
}

最佳答案

查询:

@Query("SELECT mh.id AS id, mh.privateContent as privateContent FROM history mh WHERE mh.account = :account")

界面:

public interface HistoryDB {

    @Value("#{target.id}")
    String getId();

    @Value("#{target.privateContent}")
    String getPrivateContent();

}

您不会从查询中返回目标实体,而是返回可能尚未正确映射到投影接口(interface)的别名。

我猜您的响应看起来像 JSON 对象,其中所有字段的值为 null。 (如果我错了请纠正我)。

更新1:

还可以通过转换器的 bean 暴露从投影接口(interface)手动调用属性转换器:

@Component //Singleton proxy instance in application context (no huge impact)
public class CryptoConverter implements AttributeConverter<String, String> {}

然后使用它的投影方法:<​​/p>

public interface HistoryDB {

    @Value("#{target.id}") // May omit if works without @Value
    String getId();

    @Value("#{@cryptoConverter.convertToEntityAttribute(target.privateContent)}")
    String getPrivateContent();

}

关于java - Spring转换器不转换自定义实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60638653/

相关文章:

Java 如何在 SystemInitializer 类中使用 Spring Autowired

java - Oracle hibernate : Ordinal binding and Named binding cannot be combined

java - 在@ManyToOne 端合并托管实体

c# - 一次又一次地以相同的方式重命名文件

Java2D 图形抗锯齿

java - 使用 RestTemplate 的 Spring Boot 多部分内容类型 HTTP 请求

spring - Spring MVC 测试中的空异常主体

java - Spring Batch - 步骤不再执行 : Step already complete or not restartable

multithreading - 使用 Hibernate SessionFactory 的多线程问题

java - 如何让用户设置背景颜色?