Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle Hibernate使用BigDecimal而不是Int_Oracle_Hibernate_Jpa_Kotlin - Fatal编程技术网

Oracle Hibernate使用BigDecimal而不是Int

Oracle Hibernate使用BigDecimal而不是Int,oracle,hibernate,jpa,kotlin,Oracle,Hibernate,Jpa,Kotlin,我让Oracle type将integer\u varray类型创建或替换为int的varray(4000)然后是使用此类型的表。(Oracle DB-12.1.0.2) hibernate中的实体将IntArray作为一个类型,并且IntArrayType来自这个库(实际上,它是库还是我自己的实现并不重要,两种情况下的行为都是相同的) 问题是Hibernate将此数组视为BigDecimal的数组,因此当Hibernate类型尝试将其强制转换为Int时,它会引发异常 如何强制Hibernate

我让Oracle type
将integer\u varray类型创建或替换为int的varray(4000)然后是使用此类型的表。(Oracle DB-12.1.0.2)

hibernate中的实体将
IntArray
作为一个类型,并且
IntArrayType
来自这个库(实际上,它是库还是我自己的实现并不重要,两种情况下的行为都是相同的)

问题是Hibernate将此数组视为
BigDecimal
的数组,因此当Hibernate类型尝试将其强制转换为
Int
时,它会引发异常

如何强制Hibernate在此自定义类型中使用
Int
而不是
BigDecimal
?具有
Int
的其他字段的行为与Int相同,但此特定类型的字段的行为不正确

一些代码: SQL表:

create or replace type integer_varray as varray (4000) of int;
create table plan_capacities
(
  id       int generated by default as identity not null constraint plan_capacities_pkey primary key,
  line_id  int references lines (id) on delete cascade,
  model_id int references models (id) on delete cascade,
  plan_id  int references plans (id) on delete cascade,
  capacity integer_varray
);
实体:

@Entity()
@Table(name = "plan_capacities")
@TypeDefs(
        TypeDef(name = "int-array", typeClass = IntArrayType::class)
)
data class PlanCapacity(
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val id: Int,

        @ManyToOne
        @JoinColumn(name = "line_Id")
        val line: Line,

        @ManyToOne()
        @JoinColumn(name = "model_Id")
        val model: Model,

        @JsonBackReference
        @ManyToOne()
        @JoinColumn(name = "plan_id")
        val plan: Plan,

        @Column(name = "capacity")
        @Type(type = "int-array")
        val capacity: IntArray
) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as PlanCapacity

        if (id != other.id) return false
        if (line != other.line) return false
        if (model != other.model) return false
        if (plan != other.plan) return false
        if (!Arrays.equals(capacity, other.capacity)) return false

        return true
    }

    override fun hashCode(): Int {
        var result = id
        result = 31 * result + line.hashCode()
        result = 31 * result + model.hashCode()
        result = 31 * result + plan.hashCode()
        result = 31 * result + Arrays.hashCode(capacity)
        return result
    }
}

解决方案是派生
UserType

class IntArrayOracleType : UserType {
    override fun assemble(cached: Serializable?, owner: Any?) = deepCopy(cached)

    override fun deepCopy(value: Any?) = (anyToIntArraySafe(value))?.copyOf()

    override fun disassemble(value: Any?) = deepCopy(value)

    override fun equals(x: Any?, y: Any?) = (x?.equals(y) ?: y?.equals(x)) ?: true

    override fun hashCode(x: Any?) = x?.hashCode() ?: 0

    override fun isMutable() = true

    override fun nullSafeGet(resultSet: ResultSet,
                             names: Array<out String>?,
                             session: SharedSessionContractImplementor?,
                             owner: Any?): Any? {
        if (resultSet.wasNull() || names == null) {
            return null
        }

        return anyToIntArraySafe(resultSet.getArray(names[0])?.array) ?: intArrayOf()
    }

    override fun nullSafeSet(statement: PreparedStatement, value: Any?, index: Int, session: SharedSessionContractImplementor) {
        val connection = statement.connection
        if (value == null) {
            statement.setNull(index, Types.ARRAY, "INTEGER_VARRAY")
        } else {
            val oraConnection = connection.unwrap(OracleConnection::class.java)
            val array = oraConnection.createOracleArray("INTEGER_VARRAY", value)
            statement.setArray(index, array)
        }
    }

    override fun replace(original: Any?, target: Any?, owner: Any?) = (anyToIntArraySafe(original))?.copyOf()

    override fun returnedClass() = IntArray::class.java

    override fun sqlTypes() = intArrayOf(Types.ARRAY)
}

/**
 * Takes Any? and tries to cast it to Array and than to IntArray - BigDecimal is checked.
 *
 * Note that when given array contains anything else then BigDecimal or Int exception will be thrown
 * @return IntArray if successfully casted, null otherwise
 * */
internal fun anyToIntArraySafe(array: Any?) = (array as? IntArray) ?: (array as? Array<*>)?.map {
    it as? Int ?: (it as BigDecimal).intValueExact()
}?.toIntArray()
类IntArrayOracleType:UserType{
覆盖乐趣汇编(缓存:可序列化?、所有者:任何?)=deepCopy(缓存)
override fun deepCopy(值:Any?=(anyToIntArraySafe(值))?.copyOf()
覆盖(值:任何?)=deepCopy(值)
覆盖乐趣等于(x:Any?,y:Any?=(x?.equals(y)?:y?.equals(x))?:真
重写有趣的hashCode(x:Any?=x?.hashCode()?:0
可重写()=true
重写fun nullSafeGet(resultSet:resultSet,
名称:数组?,
会话:SharedSessionCompactmentor?,
业主:有吗?):有吗{
if(resultSet.wasNull()| | names==null){
返回空
}
返回anyToIntArraySafe(resultSet.getArray(名称[0])?.array)?:intArrayOf()
}
重写nullSafeSet(语句:PreparedStatement,值:Any?,索引:Int,会话:SharedSessionCompactImplementor){
val connection=statement.connection
如果(值==null){
语句.setNull(索引,Types.ARRAY,“INTEGER\u VARRAY”)
}否则{
val oraConnection=connection.unwrap(OracleConnection::class.java)
val array=oraConnection.createOracleArray(“INTEGER_VARRAY”,value)
语句.setArray(索引,数组)
}
}
覆盖乐趣替换(原始:任意?,目标:任意?,所有者:任意?=(anyToIntArraySafe(原始))?.copyOf()
重写fun returnedClass()=IntArray::class.java
重写fun sqlTypes()=intArrayOf(Types.ARRAY)
}
/**
*吃点什么?并尝试将其强制转换为数组,而不是IntArray-已选中BigDecimal。
*
*请注意,当给定数组包含任何其他内容时,将抛出BigDecimal或Int异常
*@return IntArray如果成功铸造,则为null
* */
内部趣味anyToIntArraySafe(数组:Any?=(数组作为?IntArray)?:(数组作为?数组)?.map{
它是?Int?:(它是BigDecimal.intValueExact()
}?toIntArray()

这里将
BigDecimal
转换为
Int
。然后只需将
IntArrayType
更改为
IntArrayType
,现在它就可以工作了。

这里有些代码可能会有所帮助。我添加了实体代码和SQL表定义