当项目同时使用MySQL和PostgreSQL时,从JsonStringType切换到JsonBinaryType
当项目同时使用MySQL和PostgreSQL时,从JsonStringType切换到JsonBinaryType,mysql,postgresql,hibernate,mariadb,hibernate-types,Mysql,Postgresql,Hibernate,Mariadb,Hibernate Types,当需要从PostgreSQL切换到MariaDB/MySql时,我对json列有一个问题。 我使用Spring Boot+JPA+Hibernate+Hibernate-types-52。 我要映射的表如下: CREATE TABLE atable( ... acolumn JSON, ... ); 好的,它适用于PostgreSQL和MariaDB/MySql。 问题是,当我想要部署一个可以轻松地从一个切换到另一个的应用程序时,因为PostgreSQL和MySQL/MariaDB的正
当需要从PostgreSQL切换到MariaDB/MySql时,我对json列有一个问题。
我使用Spring Boot+JPA+Hibernate+Hibernate-types-52。
我要映射的表如下:
CREATE TABLE atable(
...
acolumn JSON,
...
);
好的,它适用于PostgreSQL和MariaDB/MySql。问题是,当我想要部署一个可以轻松地从一个切换到另一个的应用程序时,因为PostgreSQL和MySQL/MariaDB的正确hibernate-types-52实现是不同的
这适用于MySQL/MariaDB
@Entity
@Table(name = "atable")
@TypeDef(name = "json", typeClass = JsonStringType.class)
public class Atable {
...
@Type(type = "json")
@Column(name = "acolumn", columnDefinition = "json")
private JsonNode acolumn;
...
}
这适用于PosgreSQL@Entity
@Table(name = "atable")
@TypeDef(name = "json", typeClass = JsonBinaryType.class)
public class Atable {
...
@Type(type = "json")
@Column(name = "acolumn", columnDefinition = "json")
private JsonNode acolumn;
...
}
任何从JsonBinaryType切换到JsonStringType的解决方案(或解决此问题的任何其他解决方案)都值得赞赏。从Hibernate Types项目的
2.11
版本开始,您只需使用JsonType
,它可以与PostgreSQL、MySQL、Oracle、SQL Server或H2一起使用
因此,使用JsonType
而不是JsonBinaryType
或JsonStringType
@Entity
@Table(name = "atable")
@TypeDef(name = "json", typeClass = JsonType.class)
public class Atable {
@Type(type = "json")
@Column(name = "acolumn", columnDefinition = "json")
private JsonNode acolumn;
}
就这样 您可以做一些疯狂的事情,但这仅适用于特定类型和列: 首先,要用动态映射替换静态
@TypeDef
:
您可以使用hibernateproperties自定义程序
添加typecontributor列表
:
@Configuration
public class HibernateConfig implements HibernatePropertiesCustomizer {
@Value("${spring.jpa.database-platform:}")
private Class<? extends Driver> driverClass;
@Override
public void customize(Map<String, Object> hibernateProperties) {
AbstractHibernateType<Object> jsonType;
if (driverClass != null && PostgreSQL92Dialect.class.isAssignableFrom(driverClass)) {
jsonType = new JsonBinaryType(Atable.class);
} else {
jsonType = new JsonStringType(Atable.class);
}
hibernateProperties.put(EntityManagerFactoryBuilderImpl.TYPE_CONTRIBUTORS,
(TypeContributorList) () -> List.of(
(TypeContributor) (TypeContributions typeContributions, ServiceRegistry serviceRegistry) ->
typeContributions.contributeType(jsonType, "myType")));
}
}
作为演示,我只检查PostgreSQL,并且只将动态列定义应用于特定实体中的特定列:
public class JsonColumnMappingIntegrator implements Integrator {
public static final JsonColumnMappingIntegrator INSTANCE =
new JsonColumnMappingIntegrator();
@Override
public void integrate(
Metadata metadata,
SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
Database database = metadata.getDatabase();
if (PostgreSQL92Dialect.class.isAssignableFrom(database.getDialect().getClass())) {
Column acolumn=
((Column) metadata.getEntityBinding(Atable.class.getName()).getProperty("acolumn").getColumnIterator().next());
settingsCol.setSqlType("json");
}
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
}
}
metadata.getEntityBindings()
将为您提供所有实体绑定,您可以在这些绑定上迭代,然后再迭代属性。但这似乎效率很低。
我也不确定是否可以设置诸如“IS JSON”约束等,因此自定义创建脚本会更好。从avalue更改为acolumn…好的,似乎反序列化有问题。。。查看itRight,因此不会调用
setParameters
方法。TypeContributors似乎不支持参数化类型:可以用具体类型实例化Json*类型。这意味着您必须为要使用的每个(基本)类创建一个自定义类型…请查看我的更新答案。事实上,你可以删除你的评论,因为它不再相关。
public class JsonColumnMappingIntegrator implements Integrator {
public static final JsonColumnMappingIntegrator INSTANCE =
new JsonColumnMappingIntegrator();
@Override
public void integrate(
Metadata metadata,
SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
Database database = metadata.getDatabase();
if (PostgreSQL92Dialect.class.isAssignableFrom(database.getDialect().getClass())) {
Column acolumn=
((Column) metadata.getEntityBinding(Atable.class.getName()).getProperty("acolumn").getColumnIterator().next());
settingsCol.setSqlType("json");
}
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
}
}