JPA使用pg数据库时,bool字段不能跨库迁移的解决方案

首先,大多数人的印象里,hibernate作为一个笨重学习成本高的近乎全自动的框架它的优点就是可以支持很多数据库,但是最近研究发现,java中的boolean类型的字段,在mariadb/mysql 中为bit 0/1,在sqlserver/oracle中为bit 0/1 numeric(1,0) check * in (0,1),然而在PG数据库中却是bool,因为pg就是支持boolean到bool的映射

所以,java中的boolean 在除PG的数据库之外的几个常见数据库中存储的都是 0/1,这就导致了数据迁移时会出现不兼容的问题。

在GPT的帮助下,经研究hibernate的数据库方言发现,可以通过修改官方的方言以达到实现兼容的目的。

相关代码如下:

 1 package com.example.demo.jpa.dialect;
 2 
 3 import java.sql.Types;
 4 
 5 import org.hibernate.boot.model.TypeContributions;
 6 import org.hibernate.dialect.PostgreSQLDialect;
 7 import org.hibernate.service.ServiceRegistry;
 8 import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
 9 import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
10 
11 /***
12  * 将java中的bool 处理成pg中的numeric(1,0)
13  * 
14  *
15  */
16 public class PgDialect extends PostgreSQLDialect {
17 
18     @Override
19     public int getPreferredSqlTypeCodeForBoolean() {
20         return Types.NUMERIC;
21     }
22 
23     @Override
24     public String toBooleanValueString(boolean bool) {
25         // 将布尔值映射为 numeric(1, 0)
26         return bool ? "1" : "0";
27     }
28 
29     @Override
30     public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
31         super.contributeTypes(typeContributions, serviceRegistry);
32         // 把java中的Boolean转为0/1 把数据库中的0/1 转为Boolean
33         typeContributions.getTypeConfiguration().getJavaTypeRegistry().addDescriptor(new PgBooleanJavaType());
34         final DdlTypeRegistry ddlTypeRegistry = typeContributions.getTypeConfiguration().getDdlTypeRegistry();
35         ddlTypeRegistry.addDescriptor(new DdlTypeImpl(Types.BOOLEAN, "numeric(1,0) ", this));
36     }
37 
38 }

 

 1 package com.example.demo.jpa.dialect;
 2 
 3 import java.math.BigDecimal;
 4 import java.util.Objects;
 5 
 6 import org.hibernate.type.descriptor.WrapperOptions;
 7 import org.hibernate.type.descriptor.java.BooleanJavaType;
 8 
 9 /**
10  * 当从数据库的字段类型为Boolean时,如何与java中的boolean互相映射
11  *
12  */
13 public class PgBooleanJavaType extends BooleanJavaType {
14 
15     private static final long serialVersionUID = 1L;
16 
17     @SuppressWarnings("unchecked")
18     @Override
19     public <X> X unwrap(Boolean value, Class<X> type, WrapperOptions options) {
20         if (value == null) {
21             return null;
22         } else if (BigDecimal.class.isAssignableFrom(type)) {
23             return (X) (Objects.equals(true, value) ? new BigDecimal(1) : new BigDecimal(0));
24         } else if (Boolean.class.equals(type)) {
25             return (X) value;
26         } else if (Byte.class.equals(type)) {
27             return (X) toByte(value);
28         }
29         if (Short.class.equals(type)) {
30             return (X) toShort(value);
31         } else if (Integer.class.equals(type)) {
32             return (X) toInteger(value);
33         } else if (Long.class.equals(type)) {
34             return (X) toLong(value);
35         } else if (Character.class.equals(type)) {
36             return (X) Character.valueOf(value ? '1' : '0');
37         } else if (String.class.equals(type)) {
38             return (X) (value ? "1" : "0");
39         }
40         throw unknownUnwrap(type);
41     }
42 
43 }

 

posted @ 2024-05-13 08:37  漫漫人生路总会错几步  阅读(16)  评论(0编辑  收藏  举报