oracle - Hibernate 使用 BigDecimal 而不是 Int
问题描述
我有 Oracle 类型create or replace type integer_varray as varray (4000) of int;
,然后是使用这种类型的表。(甲骨文数据库 - 12.1.0.2)
hibernate 中的实体IntArray
作为一种类型,IntArrayType
来自这个库https://github.com/vladmihalcea/hibernate-types(实际上它是库还是我自己的实现并不重要,这两种情况的行为都是相同的)。
问题是 Hibernate 将此数组视为数组,BigDecimal
因此当 hibernate-types 尝试将其强制转换为Int
.
如何强制 Hibernate 使用Int
而不是BigDecimal
在此自定义类型中使用?其他字段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()
在这里BigDecimal
投到Int
. 然后只需更改IntArrayType
为IntArrayOracleType
,现在它可以工作了。
推荐阅读
- mongodb - spring mongotemplate查询追加一个数组正在创建数组数组
- python - 从 WTForms 解析成 MongoDB 中的数组
- docker - 如何在不停机的情况下将 dockerized Jira 升级到最新版本
- flutter - 如何在有条件的情况下致电提供者?
- android - 证明Android Pie中的角色正常权限
- amazon-web-services - AWS Lambda | 如何获取经过身份验证的用户子
- python - Python 重组 PCAP JSON 数据
- javascript - 循环遍历数据并将其传递给图表
- php - 在电子邮件中发送正文内容和日历邀请
- streaming - XSLT 流式传输不流式传输