当有必要从PostgreSQL切换到MariaDB/MySql时,我遇到了json列的问题。
我使用Spring + JPA + Hibernate +hibernate-types 52。
我想要映射的桌子是这样的:
CREATE TABLE atable(
...
acolumn JSON,
...
);好的,它适用于PostgreSQL和MariaDB/MySql。
问题是,当我希望部署一个应用程序时,它可以轻松地从一个应用程序切换到另一个应用程序,因为PostgreSQL和MySQL/MariaDB的正确hibernate类型-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 (或任何其他解决方案,以解决这一问题)将受到赞赏。
发布于 2020-01-15 14:56:33
从Hibernate类型项目的2.11版本开始,您可以只使用JsonType,它可以与PostgreSQL、MySQL、Oracle、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;
}就这样!
发布于 2020-05-20 17:06:26
您可以做一些疯狂的事情--限制是这只适用于特定类型和列:
首先,将静态@TypeDef替换为动态映射:
可以使用HibernatePropertiesCustomizer添加TypeContributorList
@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")));
}
}因此,这仅限于现在的Atable.class,我已经将这个定制的Json类型命名为“myType”。也就是说,您用@Type(type = 'myType')注释您的属性。
我在这里使用已配置的方言,但在我的应用程序中,我正在检查特定于DB的概要文件的活动配置文件。
还请注意,自Hibernate 5.3以来,TypeContributions .contributeType(BasicType, String...)就不再受欢迎了。我还没研究过新的机制。
这就涵盖了@Type部分,但是如果您想要使用Hibernate模式生成,您仍然需要@Column(columnDefinition = "...位,所以Hibernate知道要使用哪种列类型。
这是它开始感觉有点恶心的地方。我们可以注册Integrator来操作映射元数据:
hibernateProperties.put(EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER,
(IntegratorProvider) () -> Collections.singletonList(JsonColumnMappingIntegrator.INSTANCE));作为一个演示,我只检查PostgreSQL,并且只将动态columnDefinition应用于特定实体中的特定列:
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‘约束等,所以使用自定义创建脚本会更好。
https://stackoverflow.com/questions/59703106
复制相似问题