Richard Zowalla created OPENJPA-3020:
----------------------------------------
Summary: @Lob with an AttributeConverter uses the attribute type
instead of the converter database type
Key: OPENJPA-3020
URL: https://issues.apache.org/jira/browse/OPENJPA-3020
Project: OpenJPA
Issue Type: Bug
Affects Versions: 4.1.1
Reporter: Richard Zowalla
{{@Lob}} on an attribute with a converter gets a CLOB or BLOB column chosen
from the Java type of the attribute, not from the database type of the
converter. With a converter to {{String}} on an attribute that is not a
{{String}}, the column is a BLOB:
{code:java}
@Converter
public class ItemConverter implements AttributeConverter<Item, String> { ... }
@Lob
@Convert(converter = ItemConverter.class)
private Item item; // BLOB, expected CLOB
{code}
The opposite happens for a {{String}} attribute with a converter to {{byte[]}}:
the column is a CLOB instead of a BLOB.
The stored value has the database type of the converter, so the column type
does not match it. On PostgreSQL the column is {{BYTEA}} instead of {{TEXT}}.
On MySQL and MariaDB it is {{BLOB}} instead of {{TEXT}}, and on Oracle {{BLOB}}
instead of {{CLOB}}. On Derby the insert fails:
{noformat}
XCL12: An attempt was made to put a data value of type 'java.lang.String' into
a data value of type 'BLOB'.
{noformat}
The same happens with {{<lob/>}} in a mapping file.
Cause: {{AnnotationPersistenceMappingParser.parseLobMapping()}} and
{{XMLPersistenceMappingParser.endFieldMapping()}} set the column type to CLOB
for {{String}}, {{char[]}} and {{Character[]}} attributes and to BLOB
otherwise. Both run before the converter is known.
{{ConverterValueHandler.map()}} only gives a template column, and
{{MappingInfo}} keeps the type of the column the parser created.
There is a second problem with converters to {{byte[]}}, with or without
{{@Lob}}. The column java type is {{JavaTypes.ARRAY}}, so the value is read as
an object and the converter is passed a {{java.sql.Blob}}:
{noformat}
There was an error invoking the converter ... on Java value
org.apache.derby.impl.jdbc.EmbedBlob@...: argument type mismatch
{noformat}
Reported by Francesco Chicchiriccò while testing Apache Syncope against
4.2.0-SNAPSHOT on PostgreSQL. Syncope 4.1 maps {{@Lob private String
provisions}}, which gives {{TEXT}}. Syncope 4.2 maps {{@Lob @Convert(converter
= ProvisionListConverter.class) private List<Provision> provisions}} with an
{{AttributeConverter<List<Provision>, String>}}, which gives {{BYTEA}}. The
{{List}} case needs OPENJPA-3017, but the cause is older: the code is the same
on master and in 4.1.1, and a converted attribute that is not a collection has
the same problem there.
Fix: in {{ConverterValueHandler.map()}} and {{ConverterElementHandler.map()}},
where the converter is known, change a CLOB or BLOB column to CLOB for a
converter to {{String}} and to BLOB for a converter to {{byte[]}}, and read a
{{byte[]}} database type as {{JavaSQLTypes.BYTES}}. This covers annotations,
mapping files, overrides and auto-applied converters.
Workaround: drop {{@Lob}} and declare the column type, e.g.
{{@Column(columnDefinition = "TEXT")}} on PostgreSQL (needs OPENJPA-3018 to
avoid a length being appended there).
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)