[
https://issues.apache.org/jira/browse/OPENJPA-3020?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Richard Zowalla updated OPENJPA-3020:
-------------------------------------
Description:
{{@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.
was:
{{@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).
> @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
> Assignee: Richard Zowalla
> Priority: Major
>
> {{@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.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)