gpt4 book ai didi

java - 如何更改 Hibernate CharacterTypeDescriptor 以处理空列值

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:48:09 26 4
gpt4 key购买 nike

我们的问题是由于源自 Hibernate 的 字符类型描述符。我们想更改 Hibernate 的行为以正确解析空字符串。

示例数据:

1, 'Berlin', 17277, '', 'aUser'
2, 'London', 17277, '', 'anotherUser'

我们将 hibernate 与 javax.persistence.Query 结合使用。

String sql = "SELECT * FROM table";
Query query = entityManager.createNativeQuery(sql);
List resultList = query.getResultList();

这会导致 StringIndexOutOfBoundsException,其根是来自 Hibernate 的以下代码:

if ( String.class.isInstance( value ) ) {
final String str = (String) value;
return Character.valueOf( str.charAt(0) ); // this fails, as there is no char at position 0
}

a post on the hibernate forums 证实了这一点.

我们无法从这个有问题的版本升级 hibernate 并寻找一种方法来更改 Hibernate 的映射。

我们不能使用 PreparedStatements 或普通的 JDBC-Connections 或 JPA-Entities。

改变遗留数据库也是不可能的。 SQL 语句使用 DBVisualizer 完美运行。

有没有办法改变Hibernate映射字符串的方式?

最佳答案

The CharacterType presented in this answer is available via the hibernate-types project, so there is no need to write it yourself.

首先,你需要定义一个ImmutableType:

public abstract class ImmutableType<T> implements UserType {

private final Class<T> clazz;

protected ImmutableType(Class<T> clazz) {
this.clazz = clazz;
}

@Override
public Object nullSafeGet(
ResultSet rs,
String[] names,
SharedSessionContractImplementor session,
Object owner)
throws SQLException {
return get(rs, names, session, owner);
}

@Override
public void nullSafeSet(
PreparedStatement st,
Object value,
int index,
SharedSessionContractImplementor session)
throws SQLException {
set(st, clazz.cast(value), index, session);
}

protected abstract T get(
ResultSet rs,
String[] names,
SharedSessionContractImplementor session,
Object owner) throws SQLException;

protected abstract void set(
PreparedStatement st,
T value,
int index,
SharedSessionContractImplementor session)
throws SQLException;


@Override
public Class<T> returnedClass() {
return clazz;
}

@Override
public boolean equals(Object x, Object y) {
return Objects.equals(x, y);
}

@Override
public int hashCode(Object x) {
return x.hashCode();
}

@Override
public Object deepCopy(Object value) {
return value;
}

@Override
public boolean isMutable() {
return false;
}

@Override
public Serializable disassemble(Object o) {
return (Serializable) o;
}

@Override
public Object assemble(
Serializable cached,
Object owner) {
return cached;
}

@Override
public Object replace(
Object o,
Object target,
Object owner) {
return o;
}
}

现在,我们可以开始定义实际的 CharacterType:

public class CharacterType 
extends ImmutableType<Character> {

public CharacterType() {
super(Character.class);
}

@Override
public int[] sqlTypes() {
return new int[]{Types.CHAR};
}

@Override
public Character get(
ResultSet rs,
String[] names,
SharedSessionContractImplementor session,
Object owner)
throws SQLException {
String value = rs.getString(names[0]);
return (value != null && value.length() > 0) ?
value.charAt(0) : null;
}

@Override
public void set(
PreparedStatement st,
Character value,
int index,
SharedSessionContractImplementor session)
throws SQLException {
if (value == null) {
st.setNull(index, Types.CHAR);
} else {
st.setString(index, String.valueOf(value));
}
}
}

实体映射如下所示:

@Entity(name = "Event")
@Table(name = "event")
public class Event {

@Id
@GeneratedValue
private Long id;

@Type(type = "com.vladmihalcea.book.hpjp.hibernate.type.CharacterType")
@Column(name = "event_type")
private Character type;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Character getType() {
return type;
}

public void setType(Character type) {
this.type = type;
}
}

假设我们有这些表行:

INSERT INTO event (id, event_type) VALUES (1, 'abc');    
INSERT INTO event (id, event_type) VALUES (2, '');
INSERT INTO event (id, event_type) VALUES (3, 'b');

读取所有实体时:

doInJPA(entityManager -> {
List<Event> events = entityManager.createQuery(
"select e from Event e", Event.class)
.getResultList();
for(Event event : events) {
LOGGER.info("Event type: {}", event.getType());
}
});

您将获得预期的输出:

Event type: a
Event type:
Event type: b

GitHub 上查看源代码.

关于java - 如何更改 Hibernate CharacterTypeDescriptor 以处理空列值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39615788/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com