EclipseLink 和 PostgresQL 之间似乎存在错误/不兼容。如果你只是使用 UUID 作为主键,你应该没问题。但是如果你有一个可以为空的 UUID 列,并且你尝试在其中存储 null,你会得到报告的错误:
column "whatever" is of type uuid but expression is of type character varying
请参阅:https ://bugs.eclipse.org/bugs/show_bug.cgi?id=538138 (如果有时间,请登录并投票!)
那个错误报告证明对我非常有用。特别是论坛主题的链接:
https://www.eclipse.org/forums/index.php?t=msg&th=1073632&goto=1719530&#msg_1719530
我在 SO 和网络上的其他地方尝试了各种解决方案。唯一对我有用的是大卫惠勒在那里发布的。具体来说,在数据库中创建一个转换 from character varying
to 。uuid
请注意,您必须是用户 postgres 才能创建演员表:
$ sudo su - postgres
$ psql <your database name>
# drop cast if exists (character varying as uuid);
# create or replace function uuid(_text character varying) returns uuid language sql as 'select uuid_in(_text::cstring)';
# create cast (character varying as uuid) with function uuid(character varying) as assignment;
为了完整起见,这里是我使用的其余部分(以防有帮助)
我所有的实体(具有 UUID 主键)都扩展了一个名为EntityBase
:
package com.example.entity;
import java.io.Serializable;
import java.util.UUID;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.eclipse.persistence.annotations.Convert;
import org.eclipse.persistence.annotations.Converter;
import com.example.converter.UUIDTypeConverter;
@MappedSuperclass
@Converter(name="uuidConverter", converterClass=UUIDTypeConverter.class)
public class EntityBase implements Serializable, Cloneable
{
private static final long serialVersionUID = 1L;
@Id
@Convert("uuidConverter")
private UUID id;
public EntityBase() {
this.id = UUID.randomUUID();
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof EntityBase)) {
return false;
}
EntityBase other = (EntityBase) obj;
return getId().equals(other.getId());
}
public UUID getId()
{
return this.id;
}
public void setId(UUID id)
{
this.id = id;
}
}
UUID 转换器类如下所示:
package com.example.converter;
import java.sql.Types;
import java.util.UUID;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.sessions.Session;
public class UUIDTypeConverter implements Converter
{
@Override
public UUID convertObjectValueToDataValue(Object objectValue, Session session)
{
return (UUID) objectValue;
}
@Override
public UUID convertDataValueToObjectValue(Object dataValue, Session session)
{
return (UUID) dataValue;
}
@Override
public boolean isMutable()
{
return true;
}
@Override
public void initialize(DatabaseMapping mapping, Session session)
{
DatabaseField field = mapping.getField();
field.setSqlType(Types.OTHER);
field.setTypeName("java.util.UUID");
field.setColumnDefinition("UUID");
}
}
如果您的实体的 UUID 列不是主键,则可以按如下方式对其进行注释:
import org.eclipse.persistence.annotations.Convert
import org.eclipse.persistence.annotations.Converter;
@Entity
@Converter(name="uuidConverter", converterClass=UUIDTypeConverter.class)
public class BillingEvent extends EntityBase
{
@Convert("uuidConverter")
private UUID entityId;
}
请注意,如果该实体具有使用标准javax.persistence.convert
注释的其他列,则需要区分这两个Convert
注释以避免编译错误。
例如:
import javax.persistence.Convert;
import org.eclipse.persistence.annotations.Converter;
@Entity
@Converter(name="uuidConverter", converterClass=UUIDTypeConverter.class)
public class BillingEvent extends EntityBase
{
@org.eclipse.persistence.annotations.Convert("uuidConverter")
private UUID entityId;
@Convert(converter = JSR310InstantTypeConverter.class)
private Instant createdOn;
}
我希望这可以节省其他人一些时间。祝你好运!