Richard Zowalla created OPENJPA-3014:
----------------------------------------
Summary: A named @SequenceGenerator fails where the database has
no sequences
Key: OPENJPA-3014
URL: https://issues.apache.org/jira/browse/OPENJPA-3014
Project: OpenJPA
Issue Type: Bug
Components: jpa
Reporter: Richard Zowalla
A named @SequenceGenerator fails on any database whose dictionary has no
nextSequenceQuery, for example MySQL:
org.apache.openjpa.persistence.ArgumentException: Error instantiating named
sequence "SEQGENERATOR": Your database dictionary does not support native
sequences.
at
org.apache.openjpa.jdbc.kernel.NativeJDBCSeq.endConfiguration(NativeJDBCSeq.java:190)
Found by Maxim Solodovnik while running the TCK against MySQL.
Cause: AnnotationPersistenceMetaDataParser sets the plugin of a
@SequenceGenerator to SequenceMetaData.IMPL_NATIVE unless the sequenceName is
itself a plugin string, and JDBCSeqValue maps that alias to NativeJDBCSeq,
which refuses to configure when dict.nextSequenceQuery is null. The
openjpa.Sequence setting does not help: SequenceMetaData.instantiate() consults
the configured system sequence only for the system sequence name, so a named
generator always takes the plugin path. No configuration property can therefore
avoid the failure.
Two independent parts.
1. Fall back to a table backed sequence where the database has none. OpenJPA
already ships SequenceMapping.IMPL_TABLE and IMPL_VALUE_TABLE (TableJDBCSeq,
ValueTableJDBCSeq), which keep the current value in a row of a sequence table
and update it in place, the same approach other providers take on MySQL. A
named generator resolved against a dictionary without nextSequenceQuery should
use that instead of failing, with a warning, gated on nextSequenceQuery being
null rather than on a dictionary class so every such dictionary benefits. The
substitution belongs where the sequence is resolved (SequenceMapping /
MappingRepository) so the runtime and the mapping tool behave the same; a patch
that only changes MappingTool.addSequenceComponents fixes the tool and leaves a
plain EntityManagerFactory failing, besides relying on a mutation of shared
metadata.
Two details to decide: IMPL_TABLE keys its rows per class, so entities sharing
one generator would get independent counters, whereas IMPL_VALUE_TABLE keys by
sequence name and matches @SequenceGenerator semantics more closely; and
initialValue and allocationSize travel on the SequenceMetaData rather than in
the plugin string, so they must survive the substitution.
2. Use the real thing on MariaDB. MariaDB 10.3 and later has sequence objects
(CREATE SEQUENCE, NEXT VALUE FOR, NEXTVAL()), so
MariaDBDictionary.connectedConfiguration() should set nextSequenceQuery when
the server reports 10.3 or later, in the version gated manner
PostgresDictionary already uses for storeCharsAsNumbers, and leave older
servers on the fallback from part 1.
Note for the TCK: its setup method issues CREATE SEQUENCE SEQGENERATOR START
WITH 10 through a native query and logs the failure on MySQL. That logged error
is expected there and harmless; what matters is that identifiers can still be
allocated afterwards, which part 1 provides. On MariaDB the statement succeeds,
which part 2 then uses.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)