问题描述
我目前有一个这样的字段:
I currently have a field annotated like this :
ColumnTransformer(
read="AES_DECRYPT(C_first_name, 'yourkey')",
write="AES_ENCRYPT(?, 'yourkey')")
public String getFirstName() {
return firstName;
}
这在Mysql数据库上正常工作,但是我需要此配置是可选的,因为我们的应用程序可以根据启动参数使用另一个数据库(HsqlDB).因此,我需要的是一种仅在使用特定的开始参数时才使用ColumnTransformer的方法(对于HsqlDB,则不使用ColumnTransformer,而不能使用"AES_ENCRYPT")
This is working properly with a Mysql database, but I need this configuration to be optional, because our application can use another database (HsqlDB) depending on start parameters. So what I need is a way to use a ColumnTransformer only when a specific start parameter is used (and no ColumnTransformer for HsqlDB, which cant use "AES_ENCRYPT")
有人可以帮我吗?
推荐答案
我遇到了同样的问题,我希望密钥是可配置的.我为此项目找到的唯一解决方案是在运行时更新注释值.是的,我知道这听起来很糟糕,但据我所知,没有其他方法.
I had same problem, I want key to be configurable. The only solution i found for this item is to update annotation values at runtime. Yes, i know that this sounds awful, but as far as i know there is no other way.
实体类:
@Entity
@Table(name = "user")
public class User implements Serializable {
@Column(name = "password")
@ColumnTransformer(read = "AES_DECRYPT(password, '${encryption.key}')", write = "AES_ENCRYPT(?, '${encryption.key}')")
private String password;
}
我实现了将$ {encryption.key}替换为其他值的类(在我的情况下是从Spring应用程序上下文加载的)
I implemented class that replaces ${encryption.key} to the some other value (in my case loaded from Spring application context)
import org.hibernate.annotations.ColumnTransformer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.Map;
import javax.annotation.PostConstruct;
@Component(value = "transformerColumnKeyLoader")
public class TransformerColumnKeyLoader {
public static final String KEY_ANNOTATION_PROPERTY = "${encryption.key}";
@Value(value = "${secret.key}")
private String key;
@PostConstruct
public void postConstruct() {
setKey(User.class, "password");
}
private void setKey(Class<?> clazz, String columnName) {
try {
Field field = clazz.getDeclaredField(columnName);
ColumnTransformer columnTransformer = field.getDeclaredAnnotation(ColumnTransformer.class);
updateAnnotationValue(columnTransformer, "read");
updateAnnotationValue(columnTransformer, "write");
} catch (NoSuchFieldException | SecurityException e) {
throw new RuntimeException(
String.format("Encryption key cannot be loaded into %s,%s", clazz.getName(), columnName));
}
}
@SuppressWarnings("unchecked")
private void updateAnnotationValue(Annotation annotation, String annotationProperty) {
Object handler = Proxy.getInvocationHandler(annotation);
Field merberValuesField;
try {
merberValuesField = handler.getClass().getDeclaredField("memberValues");
} catch (NoSuchFieldException | SecurityException e) {
throw new IllegalStateException(e);
}
merberValuesField.setAccessible(true);
Map<String, Object> memberValues;
try {
memberValues = (Map<String, Object>) merberValuesField.get(handler);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
Object oldValue = memberValues.get(annotationProperty);
if (oldValue == null || oldValue.getClass() != String.class) {
throw new IllegalArgumentException(String.format(
"Annotation value should be String. Current value is of type: %s", oldValue.getClass().getName()));
}
String oldValueString = oldValue.toString();
if (!oldValueString.contains(TransformerColumnKeyLoader.KEY_ANNOTATION_PROPERTY)) {
throw new IllegalArgumentException(
String.format("Annotation value should be contain %s. Current value is : %s",
TransformerColumnKeyLoader.KEY_ANNOTATION_PROPERTY, oldValueString));
}
String newValueString = oldValueString.replace(TransformerColumnKeyLoader.KEY_ANNOTATION_PROPERTY, key);
memberValues.put(annotationProperty, newValueString);
}
}
此代码应在创建EntityManager之前运行.在我的情况下,我使用了depend-on(对于xml配置或对于Java配置的@DependsOn).
This code should be run before creating EntityManager. In my case i used depends-on (for xml config or @DependsOn for java config).
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="transformerColumnKeyLoader"> ... </bean>
这篇关于我想知道Hibernate是否可以执行ColumnTransformer的程序化配置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!