OPENJPA-2558 implement BooleanRepresentation which can be switched via config

Each DBDictionary has it's own default BooleanRepresentation but can easily get changed by the user
e.g. via
<property name="openjpa.jdbc.DBDictionary"
    value="(BitTypeName=CHAR(1),BooleanTypeName=CHAR(1),BooleanRepresentation=STRING_10)"/>


git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1652761 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Struberg 2015-01-18 14:30:44 +00:00
parent 4ca9dbd741
commit c5e4fac841
8 changed files with 537 additions and 36 deletions

View File

@ -0,0 +1,303 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.jdbc.sql;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.UserException;
/**
* <p>Defines how a {@code Boolean} or {@code boolean} value
* gets stored in the database by default.</p>
*
* <p>The {@link DBDictionary} defines a default representation for {@code Boolean}
* and {@code boolean} fields in JPA entities. The {@link org.apache.openjpa.jdbc.sql.OracleDictionary}
* for example uses a {@code NUMBER(1)} with the values {@code (int) 1} and {@code (int) 0} by default.
* However, sometimes you like to use a different default representation for Boolean values in your database.
* If your application likes to store boolean values in a {@code CHAR(1)} field with {@code "T"} and
* {@code "F"} values then you might configure the {@link org.apache.openjpa.jdbc.sql.DBDictionary}
* to use the {@link org.apache.openjpa.jdbc.sql.BooleanRepresentation.BooleanRepresentations#STRING_TF}
* BooleanRepresentation:
* <pre>
* &lt;property name="openjpa.jdbc.DBDictionary"
* value="(BitTypeName=CHAR(1),BooleanTypeName=CHAR(1),BooleanRepresentation=STRING_10)"/&gt
* </pre>
*
* Please note that you still need to adopt the mapping separately by setting the
* {@code BitTypeName} and/or {@code BooleanTypeName} (depending on your database) to
* the desired type in the database.
* </p>
*
* <p>The following {@code BooleanRepresentation} configuration options are possible:
* <ul>
* <li>One of the enum values of {@link org.apache.openjpa.jdbc.sql.BooleanRepresentation.BooleanRepresentations}
* , e.g.:
* <pre>
* &lt;property name="openjpa.jdbc.DBDictionary" value="(BooleanRepresentation=STRING_YN)"/&gt
* </pre>
* </li>
* <li>
* Two slash ({@code '/'}) separated true/false value strings:
* <pre>
* &lt;property name="openjpa.jdbc.DBDictionary" value="(BooleanRepresentation=oui/non)"/&gt
* </pre>
* </li>
* <li>
* A fully qualified class name of your own {@link org.apache.openjpa.jdbc.sql.BooleanRepresentation}
* implementation, e.g.:
* <pre>
* &lt;property name="openjpa.jdbc.DBDictionary"
* value="(BooleanRepresentation=com.mycompany.MyOwnBoolRepresentation)"/&gt
* </pre>
* </li>
* </ul>
*
* </p>
*
* <p>If a single column uses a different representation then they
* still can tweak this for those columns with the
* {@code org.apache.openjpa.persistence.ExternalValues} annotation.</p>
*/
public interface BooleanRepresentation {
/**
* Set the boolean value into the statement
* @param stmnt
* @param columnIndex
* @param val the boolean value to set
* @throws SQLException
*/
public void setBoolean(PreparedStatement stmnt, int columnIndex, boolean val) throws SQLException;
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException;
public static class Factory {
public static BooleanRepresentation valueOf(String booleanRepresentationKey, ClassLoader cl) {
BooleanRepresentation booleanRepresentation = null;
// 1st step, try to lookup the BooleanRepresentation from the default ones
try {
booleanRepresentation = BooleanRepresentations.valueOf(booleanRepresentationKey);
}
catch (IllegalArgumentException iae) {
// nothing to do
}
if (booleanRepresentation == null && booleanRepresentationKey.contains("/")) {
// if the key contains a '/' then the first value is the key for 'true', the 2nd value is for 'false'
String[] vals = booleanRepresentationKey.split("/");
if (vals.length == 2) {
booleanRepresentation = new StringBooleanRepresentation(vals[0], vals[1]);
}
}
else {
// or do a class lookup for a custom BooleanRepresentation
try {
Class<? extends BooleanRepresentation> booleanRepresentationClass
= (Class<? extends BooleanRepresentation>) cl.loadClass(booleanRepresentationKey);
booleanRepresentation = booleanRepresentationClass.newInstance();
}
catch (Exception e) {
// nothing to do
//X TODO probably log some error?
}
}
if (booleanRepresentation == null) {
Localizer _loc = Localizer.forPackage(BooleanRepresentation.class);
throw new UserException(_loc.get("unknown-booleanRepresentation",
new Object[]{booleanRepresentationKey,
Arrays.toString(BooleanRepresentation.BooleanRepresentations.values())}
));
}
else {
//X TODO add logging about which one got picked up finally
}
return booleanRepresentation;
}
}
/**
* BooleanRepresentation which takes 2 strings for true and false representations
* as constructor parameter;
*/
public static class StringBooleanRepresentation implements BooleanRepresentation {
private final String trueRepresentation;
private final String falseRepresentation;
public StringBooleanRepresentation(String trueRepresentation, String falseRepresentation) {
this.trueRepresentation = trueRepresentation;
this.falseRepresentation = falseRepresentation;
}
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val) throws SQLException{
stmnt.setString(idx, val ? trueRepresentation : falseRepresentation);
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return trueRepresentation.equals(rs.getString(columnIndex));
}
@Override
public String toString() {
return "StringBooleanRepresentation with the following values for true and false: "
+ trueRepresentation + " / " + falseRepresentation;
}
}
public enum BooleanRepresentations implements BooleanRepresentation {
/**
* Booleans are natively supported by this very database.
* The database column is e.g. a NUMBER(1)
* OpenJPA will use preparedStatement.setBoolean(..) for it
*/
BOOLEAN {
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val) throws SQLException {
stmnt.setBoolean(idx, val);
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return rs.getBoolean(columnIndex);
}
},
/**
* Booleans are stored as numeric int 1 and int 0 values.
* The database column is e.g. a NUMBER(1)
* OpenJPA will use preparedStatement.setInt(..) for it
*/
INT_10 {
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val) throws SQLException{
stmnt.setInt(idx, val ? 1 : 0);
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return rs.getInt(columnIndex) > 0;
}
},
/**
* Booleans are stored as String "1" for {@code true}
* and String "0" for {@code false}.
* The database column is e.g. a CHAR(1) or VARCHAR(1)
* OpenJPA will use preparedStatement.setString(..) for it
*/
STRING_10 {
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val) throws SQLException{
stmnt.setString(idx, val ? "1" : "0");
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return "1".equals(rs.getString(columnIndex));
}
},
/**
* Booleans are stored as String "Y" for {@code true}
* and String "N" for {@code false}.
* The database column is e.g. a CHAR(1) or VARCHAR(1)
* OpenJPA will use preparedStatement.setString(..) for it
*/
STRING_YN {
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val) throws SQLException{
stmnt.setString(idx, val ? "Y" : "N");
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return "Y".equals(rs.getString(columnIndex));
}
},
/**
* Booleans are stored as String "y" for {@code true}
* and String "n" for {@code false}.
* The database column is e.g. a CHAR(1) or VARCHAR(1)
* OpenJPA will use preparedStatement.setString(..) for it
*/
STRING_YN_LOWERCASE {
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val) throws SQLException{
stmnt.setString(idx, val ? "y" : "n");
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return "y".equals(rs.getString(columnIndex));
}
},
/**
* Booleans are stored as String "T" for {@code true}
* and String "F" for {@code false}.
* The database column is e.g. a CHAR(1) or VARCHAR(1)
* OpenJPA will use preparedStatement.setString(..) for it
*/
STRING_TF {
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val) throws SQLException{
stmnt.setString(idx, val ? "T" : "F");
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return "T".equals(rs.getString(columnIndex));
}
},
/**
* Booleans are stored as String "t" for {@code true}
* and String "f" for {@code false}.
* The database column is e.g. a CHAR(1) or VARCHAR(1)
* OpenJPA will use preparedStatement.setString(..) for it
*/
STRING_TF_LOWERCASE {
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val) throws SQLException{
stmnt.setString(idx, val ? "t" : "f");
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return "t".equals(rs.getString(columnIndex));
}
};
}
}

View File

@ -178,9 +178,9 @@ public class DBDictionary
private static final Localizer _loc = Localizer.forPackage(DBDictionary.class);
// Database version info preferably set from Connection metadata
private int major;
private int minor;
private int major;
private int minor;
// schema data
public String platform = "Generic";
public String databaseProductName = "";
@ -326,7 +326,14 @@ public class DBDictionary
*/
public enum DateMillisecondBehaviors { DROP, ROUND, RETAIN };
private DateMillisecondBehaviors dateMillisecondBehavior;
/**
* Defines how {@code Boolean} and {@code boolean} values get represented
* in OpenJPA. Default to {@link org.apache.openjpa.jdbc.sql.BooleanRepresentation.BooleanRepresentations#INT_10}
* for backward compatibility.
*/
protected BooleanRepresentation booleanRepresentation = BooleanRepresentation.BooleanRepresentations.INT_10;
public int characterColumnSize = 255;
public String arrayTypeName = "ARRAY";
public String bigintTypeName = "BIGINT";
@ -703,7 +710,7 @@ public class DBDictionary
*/
public boolean getBoolean(ResultSet rs, int column)
throws SQLException {
return rs.getBoolean(column);
return booleanRepresentation.getBoolean(rs, column);
}
/**
@ -1054,10 +1061,9 @@ public class DBDictionary
/**
* Set the given value as a parameter to the statement.
*/
public void setBoolean(PreparedStatement stmnt, int idx, boolean val,
Column col)
public void setBoolean(PreparedStatement stmnt, int idx, boolean val, Column col)
throws SQLException {
stmnt.setInt(idx, (val) ? 1 : 0);
booleanRepresentation.setBoolean(stmnt, idx, val);
}
/**
@ -1851,8 +1857,6 @@ public class DBDictionary
/**
* Helper method that inserts a size clause for a given SQL type.
*
* @see appendSize
*
* @param typeName The SQL type e.g. INT
* @param size The size clause e.g. (10)
* @return The typeName + size clause. Usually the size clause will
@ -2776,12 +2780,11 @@ public class DBDictionary
/**
* Append <code>elem</code> to <code>selectSQL</code>.
* @param selectSQL The SQLBuffer to append to.
* @param alias A {@link SQLBuffer} or a {@link String} to append.
* @param elem A {@link SQLBuffer} or a {@link String} to append.
*
* @since 1.1.0
*/
protected void appendSelect(SQLBuffer selectSQL, Object elem, Select sel,
int idx) {
protected void appendSelect(SQLBuffer selectSQL, Object elem, Select sel, int idx) {
if (elem instanceof SQLBuffer)
selectSQL.append((SQLBuffer) elem);
else
@ -3154,7 +3157,7 @@ public class DBDictionary
* getValidColumnName method of the DB dictionary should be invoked to make
* it valid.
*
* @see getValidColumnName
* @see #getValidColumnName(org.apache.openjpa.jdbc.identifier.DBIdentifier, org.apache.openjpa.jdbc.schema.Table)
*/
public final Set<String> getInvalidColumnWordSet() {
return invalidColumnWordSet;
@ -5396,11 +5399,10 @@ public class DBDictionary
* Validate that the given name is not longer than given maximum length. Uses the unqualified name
* from the supplied {@link DBIdentifier} by default..
*
* @param identifer The database identifier to check.
* @param identifier The database identifier to check.
* @param length Max length for this type of identifier
* @param msgKey message identifier for the exception.
* @param qualified If true the qualified name of the DBIdentifier will be used.
*
*
* @throws {@link UserException} with the given message key if the given name is indeed longer.
* @return the same name.
*/
@ -5412,7 +5414,7 @@ public class DBDictionary
* Validate that the given name is not longer than given maximum length. Conditionally uses the unqualified name
* from the supplied {@link DBIdentifier}.
*
* @param identifer The database identifier to check.
* @param identifier The database identifier to check.
* @param length Max length for this type of identifier
* @param msgKey message identifier for the exception.
* @param qualified If true the qualified name of the DBIdentifier will be used.
@ -5465,7 +5467,7 @@ public class DBDictionary
}
/**
* @param metadata the DatabaseMetaData to use to determine whether delimiters can be supported
* @param metaData the DatabaseMetaData to use to determine whether delimiters can be supported
*/
private void setSupportsDelimitedIdentifiers(DatabaseMetaData metaData) {
try {
@ -5673,7 +5675,23 @@ public class DBDictionary
}
}
protected boolean isUsingRange(long start, long end) {
public BooleanRepresentation getBooleanRepresentation() {
return booleanRepresentation;
}
public void setBooleanRepresentation(String booleanRepresentationKey) {
BooleanRepresentation evaluatedBooleanRepresentation = null;
if (booleanRepresentationKey != null && booleanRepresentationKey.length() > 0) {
ClassLoader cl = conf.getUserClassLoader();
evaluatedBooleanRepresentation = BooleanRepresentation.Factory.valueOf(booleanRepresentationKey, cl);
}
booleanRepresentation = evaluatedBooleanRepresentation != null
? evaluatedBooleanRepresentation
: BooleanRepresentation.BooleanRepresentations.INT_10;
}
protected boolean isUsingRange(long start, long end) {
return isUsingOffset(start) || isUsingLimit(end);
}

View File

@ -215,8 +215,7 @@ public class DBDictionaryFactory {
/**
* Guess the dictionary class name to use based on the product string.
*/
private static String dictionaryClassForString(String prod
, JDBCConfiguration conf) {
private static String dictionaryClassForString(String prod, JDBCConfiguration conf) {
if (StringUtils.isEmpty(prod))
return null;
prod = prod.toLowerCase();

View File

@ -187,6 +187,7 @@ public class PostgresDictionary
"SET", "FLOAT4", "FLOAT8", "ABSTIME", "RELTIME", "TINTERVAL",
"MONEY",
}));
booleanRepresentation = BooleanRepresentation.BooleanRepresentations.BOOLEAN;
supportsLockingWithDistinctClause = false;
supportsQueryTimeout = false;
@ -303,15 +304,6 @@ public class PostgresDictionary
}
}
@Override
public void setBoolean(PreparedStatement stmnt, int idx, boolean val,
Column col)
throws SQLException {
// postgres actually requires that a boolean be set: it cannot
// handle a numeric argument.
stmnt.setBoolean(idx, val);
}
/**
* Handle XML and bytea/oid columns in a PostgreSQL way.
*/

View File

@ -231,4 +231,5 @@ jdbc4-setbinarystream-unsupported: The JRE or JDBC level in use does not support
sequence-cache-warning: Setting the useNativeSequenceCache property on the DBDictionary no longer has an \
effect. Code has been added to allow, by default, the functionality provided in previous releases \
via the useNativeSequenceCache property.
unknown-booleanRepresentation: Unknown BooleanRepresentation {0}. Value must be one of {1}.

View File

@ -0,0 +1,159 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.jdbc.sql;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicBoolean;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement;
/**
* Test for the {@link org.apache.openjpa.jdbc.sql.BooleanRepresentation} factory and default impls
*/
public class TestBooleanRepresentation extends TestCase {
public void testBooleanRepresentation() throws Exception {
checkBooleanRepresentation("BOOLEAN", Boolean.class, Boolean.TRUE, Boolean.FALSE);
checkBooleanRepresentation("INT_10", Integer.class, 1, 0);
checkBooleanRepresentation("STRING_10", String.class, "1", "0");
checkBooleanRepresentation("STRING_YN", String.class, "Y", "N");
checkBooleanRepresentation("STRING_YN_LOWERCASE", String.class, "y", "n");
checkBooleanRepresentation("STRING_TF", String.class, "T", "F");
checkBooleanRepresentation("STRING_TF_LOWERCASE", String.class, "t", "f");
// and now up to more sophisticated ones:
checkBooleanRepresentation("oui/non", String.class, "oui", "non");
checkBooleanRepresentation(
"org.apache.openjpa.jdbc.sql.TestBooleanRepresentation$DummyTestBooleanRepresentation",
String.class, "somehowtrue", "somehowfalse");
}
private <T> void checkBooleanRepresentation(String representationKey, final Class<T> expectedType,
final T yesRepresentation, final T noRepresentation)
throws Exception {
ClassLoader cl = TestBooleanRepresentation.class.getClassLoader();
BooleanRepresentation booleanRepresentation = BooleanRepresentation.Factory.valueOf(representationKey, cl);
Assert.assertNotNull(booleanRepresentation);
DummyPreparedStatement<T> dummyPreparedStatement = new DummyPreparedStatement<T>(expectedType);
booleanRepresentation.setBoolean(dummyPreparedStatement, 1, true);
Assert.assertEquals(yesRepresentation, dummyPreparedStatement.getBooleanRepresentationValue());
booleanRepresentation.setBoolean(dummyPreparedStatement, 1, false);
Assert.assertEquals(noRepresentation, dummyPreparedStatement.getBooleanRepresentationValue());
// and also test getBoolean!
ResultSet yesRs = (ResultSet) Proxy.newProxyInstance(cl, new Class[]{ResultSet.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (String.class.equals(expectedType) && !"getString".equals(method.getName()) ||
Boolean.class.equals(expectedType) && !"getBoolean".equals(method.getName()) ||
Integer.class.equals(expectedType) && !"getInt".equals(method.getName())) {
Assert.fail("wrong ResultSet method " + method.getName()
+ "for expectedType " + expectedType.getName());
}
return yesRepresentation;
}
});
Assert.assertTrue(booleanRepresentation.getBoolean(yesRs, 1));
ResultSet noRs = (ResultSet) Proxy.newProxyInstance(cl, new Class[]{ResultSet.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (String.class.equals(expectedType) && !"getString".equals(method.getName()) ||
Boolean.class.equals(expectedType) && !"getBoolean".equals(method.getName()) ||
Integer.class.equals(expectedType) && !"getInt".equals(method.getName())) {
Assert.fail("wrong ResultSet method " + method.getName()
+ "for expectedType " + expectedType.getName());
}
return noRepresentation;
}
});
Assert.assertFalse(booleanRepresentation.getBoolean(noRs, 1));
}
/**
* A small trick to 'intercept' the PreparedStatement call inside the BooleanRepresentation
*/
public static class DummyPreparedStatement<T> extends DelegatingPreparedStatement {
private final Class<T> expectedType;
private Object booleanRepresentationValue;
public DummyPreparedStatement(Class<T> expectedType) {
super(null, null);
this.expectedType = expectedType;
}
public T getBooleanRepresentationValue() {
return (T) booleanRepresentationValue;
}
public void setBooleanRepresentationValue(T booleanRepresentationValue) {
this.booleanRepresentationValue = booleanRepresentationValue;
}
@Override
public void setBoolean(int idx, boolean b) throws SQLException {
Assert.assertEquals(Boolean.class, expectedType);
booleanRepresentationValue = b;
}
@Override
public void setString(int idx, String s) throws SQLException {
Assert.assertEquals(String.class, expectedType);
booleanRepresentationValue = s;
}
@Override
public void setInt(int idx, int i) throws SQLException {
Assert.assertEquals(Integer.class, expectedType);
booleanRepresentationValue = i;
}
}
public static class DummyTestBooleanRepresentation implements BooleanRepresentation {
@Override
public void setBoolean(PreparedStatement stmnt, int columnIndex, boolean val) throws SQLException {
stmnt.setString(columnIndex, val ? "somehowtrue" : "somehowfalse");
}
@Override
public boolean getBoolean(ResultSet rs, int columnIndex) throws SQLException {
return "somehowtrue".equals(rs.getString(columnIndex));
}
}
}

View File

@ -3568,8 +3568,9 @@ openjpa.ConnectionDriverName</literal></link>
<classname>org.apache.openjpa.jdbc.sql.DBDictionary</classname></ulink> to use
for database interaction. OpenJPA typically auto-configures the dictionary based
on the JDBC URL, but you may have to set this property explicitly if you are
using an unrecognized driver, or to plug in your own dictionary for a database
OpenJPA does not support out-of-the-box. See
using an unrecognized driver, to plug in your own dictionary for a database
OpenJPA does not support out-of-the-box, or if you like to change the default
configuration of an existing dictionary. See
<xref linkend="ref_guide_dbsetup_dbsupport"/> for details.
</para>
</section>

View File

@ -1142,6 +1142,34 @@ the <literal>INSERT/UPDATE</literal> operations with an
generated by the <literal>mappingtool</literal>.
</para>
</listitem>
<!-- MSX TODO START DOCUMENT -->
<listitem id="DBDictionary.BooleanRepresentation">
<para>
<indexterm>
<primary>
DDL
</primary>
<secondary>
BooleanRepresentation
</secondary>
</indexterm>
<literal>BooleanRepresentation</literal>:
The overridden default representation for <literal>java.lang.Boolean</literal> or
<literal>boolean</literal> fields in JPA Entities. A
<ulink url="../javadoc/org/apache/openjpa/jdbc/sql/BooleanRepresentation.html">
<classname>org.apache.openjpa.jdbc.sql.BooleanRepresentation</classname></ulink>
describes how Boolean values in entities get mapped into the database by default.
Note that you additionally might need to define the <literal>BooleanTypeName</literal>
<literal>BitTypeName</literal> settings to fit your selected BooleanRepresenation.
</para>
</listitem>
<!-- MSX TODO END DOCUMENT -->
<listitem id="DBDictionary.BooleanTypeName">
<para>
<indexterm>
@ -1152,9 +1180,9 @@ generated by the <literal>mappingtool</literal>.
BooleanTypeName
</secondary>
</indexterm>
<literal>BooleanTypeName</literal>:
The overridden default column type for
<literal>java.sql.Types.BOOLEAN</literal>. This is used only when the schema
<literal>BooleanTypeName</literal>:
The overridden default column type for
<literal>java.sql.Types.BOOLEAN</literal>. This is used only when the schema
is generated by the <literal>mappingtool</literal>.
</para>
</listitem>