使用@TypeDefs自定义数据类型

本文介绍如何在Java中使用@TypeDefs注解自定义数据类型,特别是针对Long数组的情况。通过定义ArraySqlTypeDescriptor和AbstractArrayTypeDescriptor,实现了将数据库中的bigint[]类型映射到Long数组,避免使用bytea类型。同时提到了使用自定义的LongArrayTypeDescriptor和LongArrayType,并在实际应用中如何操作这些自定义类型。文中还提及了辅助类ArrayUtil在数据处理中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用@TypeDefs自定义数据类型

  • 使用场景:自定义Long数组,使数据库数据类型为bigint[],而不是bytea

实现

  1. 定义公共的ArraySqlTypeDescriptor
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.BasicBinder;
import org.hibernate.type.descriptor.sql.BasicExtractor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;

import java.sql.*;

public class ArraySqlTypeDescriptor implements SqlTypeDescriptor {
   

    public static final ArraySqlTypeDescriptor INSTANCE = new ArraySqlTypeDescriptor();

    @Override
    public int getSqlType() {
   
        return Types.ARRAY;
    }

    @Override
    public boolean canBeRemapped() {
   
        return true;
    }

    @Override
    public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
   
        return new BasicBinder<X>(javaTypeDescriptor, this) {
   
            @Override
            protected void doBind(
                    PreparedStatement st,
                    X value,
                    int index,
                    WrapperOptions options
            ) throws SQLException {
   
                AbstractArrayTypeDescriptor<Object> abstractArrayTypeDescriptor
                        = (AbstractArrayTypeDescriptor<Object>) javaTypeDescriptor;
                st.setArray(
                        index,
                        st.getConnection().createArrayOf(
                                abstractArrayTypeDescriptor.getSqlArrayType(),
                                abstractArrayTypeDescriptor.unwrap(
                                        value,
                                        Object[].class,
                                        options
                                )
                        )
                );
            }

            @Override
            protected void doBind(
                    CallableStatement st,
                    X value,
                    String name,
                    WrapperOptions options
            ) throws SQLException {
   
                throw new UnsupportedOperationException(
                        "Binding by name is not supported!"
                );
            }
        };
    }

    @Override
    public <X> ValueExtractor<X> getExtractor(
            final JavaTypeDescriptor<X> javaTypeDescriptor) {
   
        return new BasicExtractor<X>(javaTypeDescriptor, this) {
   
            @Override
            protected X doExtract(
                    ResultSet rs,
                    String name,
                    WrapperOptions options
            ) throws SQLException {
   
                return javaTypeDescriptor.wrap(
                        rs.getArray(name),
                        options
                );
            }

            @Override
            protected X doExtract(
                    CallableStatement statement,
                    int index,
                    WrapperOptions options
            ) throws SQLException {
   
                return javaTypeDescriptor.wrap(
                        statement.getArray(index),
                        options
                );
            }

            @Override
            protected X doExtract(
                    CallableStatement statement,
                    String name,
                    WrapperOptions options
            ) throws SQLException {
   
                return javaTypeDescriptor.wrap(
                        statement.getArray(name),
                        options
                );
            }
        };
    }
}
    1. 定义抽象类AbstractArrayTypeDescriptor,实现解析、复制和封装数据
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.java.MutableMutabilityPlan;
import org.hibernate.usertype.DynamicParameterizedType;

import java.sql.Array;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Properties;

public abstract class AbstractArrayTypeDescriptor<T> extends AbstractTypeDescriptor<T> implements DynamicParameterizedType {
   

    private Class<T> arrayObjectClass;

    @Override
    public void setParameterValues(Properties parameters) {
   
        arrayObjectClass = ((ParameterType) parameters
                .get(PARAMETER_TYPE))
                .getReturnedClass();

    }

    public AbstractArrayTypeDescriptor(Class<T> arrayObjectClass) {
   
        super(
                arrayObjectClass,
                (MutabilityPlan<T>) new MutableMutabilityPlan<Object>() {
   
                    @Override
                    protected T deepCopyNotNull(Object value) {
   
                        return ArrayUtil.deepCopy(value);
                    }
                }
        );
        this.arrayObjectClass = arrayObjectClass;
    }

    @Override
    public boolean areEqual(Object one, Object another) {
   
        if (one == another) {
   
            return true;
        }
        if (one == null || another == null) {
   
            return false;
        }
        return ArrayUtil.isEquals(one, another);
    }

    @Override
    public String toString(Object value) {
   
        return Arrays.deepToString((Object[]) value);
    }

    @Override
    public T fromString(String string) {
   
        return ArrayUtil.fromString(
                string,
                arrayObjectClass
        );
    }

    @SuppressWarnings({
   "unchecked"}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值