在列上添加@Convert会使执行时间增加10倍以上

时间:2016-10-11 07:08:21

标签: java hibernate security

我有以下实体:

@Data
@Entity
@Table(name="\"Customer\"")
public class Customer {
    @Id
    @SequenceGenerator(name="customer_id_seq",
            sequenceName="customer_id_seq",
            allocationSize=1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
            generator="customer_id_seq")
    private long id;
    private String firstName;
    @Convert(converter = LastNameEncryption.class)
    private String lastName;
}

LastNameEncryption.java的位置:

public class LastNameEncryption implements AttributeConverter<String,String> {

    private static SecretKeySpec secretKey;
    private final static String peselKey = "somekey";

    @Override
    public String convertToDatabaseColumn(String attribute) {
        try
        {
            setKey();
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(attribute.getBytes("UTF-8")));
        }
        catch (Exception e)
        {
            System.out.println("Error while encrypting: " + e.toString());
        }
        return null;

    }

    public String convertToEntityAttribute(String dbData) {
        try {
            setKey();
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return new String(cipher.doFinal(Base64.getDecoder().decode(dbData)));
        }
        catch (Exception e)
        {
            System.out.println("Error while decrypting: " + e.toString());
        }
        return null;

    }

    public static void setKey() {
        MessageDigest sha = null;
        byte[] key;
        try {
            key = peselKey.getBytes("UTF-8");
            sha = MessageDigest.getInstance("SHA-1");
            key = sha.digest(key);
            key = Arrays.copyOf(key, 16);
            secretKey = new SecretKeySpec(key, "AES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }  catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

}

哪个应该作为一种ecnryption / decryption机制。

然而,当我添加它时,简单查询的执行时间从大约200ms增加到5.5s(原始主题here)。然后我发现,当我评论@Comment(...)注释时,查询再次顺利运行。

我犯了什么错误,或者这是正常行为吗?

注意

当我比较执行次数时,表中只有3个实体。以下是方法执行时间的日志:

Execution time of convertToEntityAttribute: 5193
Execution time of convertToEntityAttribute: 0
Execution time of convertToEntityAttribute: 0
Execution time of convertToEntityAttribute: 0

出于某种原因,第一次加密需要大约5.2秒 - 然后,时间小于1毫秒。

1 个答案:

答案 0 :(得分:0)

使用jvisualvm(包含在oracle jvm发行版中)来查明缓慢的内容。

使用Sampler标签,在触发慢速操作之前单击CPU按钮(一次不使用@Convert,一次使用注释),然后单击{{1操作完成后再按Stop按钮。然后比较两个执行配置文件你会明白到什么方法需要时间。

第一次使用加密工具或休眠或其他任何东西时,这可能是一个懒惰的初始化。

如果您很难分析cpu采样结果,请不要犹豫,回到这里并用它更新您的问题(您可以导出快照)。

与您的问题无关,我不确定建议在转换时忽略异常(如果发生异常,则返回snapshot):您可能会丢失数据。

另外,避免这样做:

null

例如,如果是 System.out.println("Error while encrypting: " + e.toString()); ,您将进入控制台:NullPointerException。只要你有堆栈跟踪,nullpointer就很容易修复。在这里你必须猜测它发生的地方。