mirror of https://github.com/apache/openjpa.git
OPENJPA-866 - Commit contributions by Tim McConnell.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@753024 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
272c584af2
commit
0e7c84ef81
|
@ -90,6 +90,13 @@ public class DynamicSchemaFactory
|
||||||
Schema schema = getSchema(schemaName);
|
Schema schema = getSchema(schemaName);
|
||||||
if (schema == null)
|
if (schema == null)
|
||||||
schema = addSchema(schemaName);
|
schema = addSchema(schemaName);
|
||||||
|
|
||||||
|
// Ensure only valid table name(s) are added to the schema
|
||||||
|
if (tableName.length() > _dict.maxTableNameLength) {
|
||||||
|
return schema.addTable(tableName,
|
||||||
|
_dict.getValidTableName(tableName, getSchema(schemaName)));
|
||||||
|
}
|
||||||
|
|
||||||
return schema.addTable(tableName);
|
return schema.addTable(tableName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +111,7 @@ public class DynamicSchemaFactory
|
||||||
/**
|
/**
|
||||||
* Table type that adds columns when {@link #getColumn} is called.
|
* Table type that adds columns when {@link #getColumn} is called.
|
||||||
*/
|
*/
|
||||||
private static class DynamicTable
|
private class DynamicTable
|
||||||
extends Table {
|
extends Table {
|
||||||
|
|
||||||
public DynamicTable(String name, Schema schema) {
|
public DynamicTable(String name, Schema schema) {
|
||||||
|
@ -118,6 +125,13 @@ public class DynamicSchemaFactory
|
||||||
Column col = super.getColumn(name);
|
Column col = super.getColumn(name);
|
||||||
if (col != null)
|
if (col != null)
|
||||||
return col;
|
return col;
|
||||||
|
|
||||||
|
// Ensure only valid column name(s) are added to the table
|
||||||
|
if (name.length() > _dict.maxColumnNameLength) {
|
||||||
|
return addColumn(name,
|
||||||
|
_dict.getValidColumnName(name, this));
|
||||||
|
}
|
||||||
|
|
||||||
return addColumn(name);
|
return addColumn(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,24 @@ public class Schema
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a table with a shortened (i.e., validated) name to the schema
|
||||||
|
*/
|
||||||
|
public Table addTable(String name, String validName) {
|
||||||
|
SchemaGroup group = getSchemaGroup();
|
||||||
|
Table tab;
|
||||||
|
if (group != null) {
|
||||||
|
group.addName(validName, true);
|
||||||
|
tab = group.newTable(validName, this);
|
||||||
|
} else
|
||||||
|
tab = new Table(validName, this);
|
||||||
|
if (_tableMap == null)
|
||||||
|
_tableMap = new TreeMap();
|
||||||
|
_tableMap.put(name.toUpperCase(), tab);
|
||||||
|
_tables = null;
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the given table from the schema.
|
* Remove the given table from the schema.
|
||||||
*
|
*
|
||||||
|
|
|
@ -297,6 +297,26 @@ public class Table
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a colum with a shortened (i.e., validated) name to the table
|
||||||
|
*/
|
||||||
|
public Column addColumn(String name, String validName) {
|
||||||
|
addName(name, true);
|
||||||
|
Schema schema = getSchema();
|
||||||
|
Column col;
|
||||||
|
if (schema != null && schema.getSchemaGroup() != null)
|
||||||
|
col = schema.getSchemaGroup().newColumn(validName, this);
|
||||||
|
else
|
||||||
|
col = new Column(validName, this);
|
||||||
|
if (_colMap == null)
|
||||||
|
_colMap = new LinkedHashMap();
|
||||||
|
_colMap.put(name.toUpperCase(), col);
|
||||||
|
_cols = null;
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the given column from the table.
|
* Remove the given column from the table.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* 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.persistence.dynamicschema;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity with very long table and column names
|
||||||
|
*
|
||||||
|
* @author Tim McConnell
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name="Very______________________________________________" +
|
||||||
|
"Long______________________________________________" +
|
||||||
|
"Table_____________________________________________" +
|
||||||
|
"Name______________________________________________" )
|
||||||
|
public class EntityVeryLongNames implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name="ID________________________________________________" +
|
||||||
|
"Very______________________________________________" +
|
||||||
|
"Long______________________________________________" +
|
||||||
|
"Column____________________________________________" +
|
||||||
|
"Name______________________________________________" )
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
@Column(name="FirstName_________________________________________" +
|
||||||
|
"Very______________________________________________" +
|
||||||
|
"Long______________________________________________" +
|
||||||
|
"Column____________________________________________" +
|
||||||
|
"Name______________________________________________" )
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
@Column(name="LastName__________________________________________" +
|
||||||
|
"Very______________________________________________" +
|
||||||
|
"Long______________________________________________" +
|
||||||
|
"Column____________________________________________" +
|
||||||
|
"Name______________________________________________" )
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
public EntityVeryLongNames() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityVeryLongNames(String firstName, String lastName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EntityVeryLongNames: id: " + getId() +
|
||||||
|
" firstName: " + getFirstName() +
|
||||||
|
" lastName: " + getLastName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result
|
||||||
|
+ ((getFirstName() == null) ? 0 : getFirstName().hashCode());
|
||||||
|
result = prime * result + getId();
|
||||||
|
result = prime * result
|
||||||
|
+ ((getLastName() == null) ? 0 : getLastName().hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final EntityVeryLongNames other = (EntityVeryLongNames) obj;
|
||||||
|
if (getId() != other.getId()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getFirstName() == null) {
|
||||||
|
if (other.getFirstName() != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!getFirstName().equals(other.getFirstName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getLastName() == null) {
|
||||||
|
if (other.getLastName() != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!getLastName().equals(other.getLastName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* 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.persistence.dynamicschema;
|
||||||
|
|
||||||
|
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||||
|
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
||||||
|
import org.apache.openjpa.jdbc.schema.Column;
|
||||||
|
import org.apache.openjpa.jdbc.schema.Table;
|
||||||
|
import org.apache.openjpa.jdbc.sql.DBDictionary;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||||
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b>TestDynamicSchemas</b> is used to create dynamic schemas for the various
|
||||||
|
* database dictionaries and validate them to ensure they are created
|
||||||
|
* correctly as specified in their dictionary. The following variables of each
|
||||||
|
* dictionary are used for validation:<p>
|
||||||
|
*
|
||||||
|
* <ol>
|
||||||
|
* <li>maxTableNameLength
|
||||||
|
* <li>maxColumnNameLength
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* <b>Note(s):</b>
|
||||||
|
* <ul>
|
||||||
|
* <li>To minimize the running time of these testcases there are no
|
||||||
|
* connections made to any of the databases
|
||||||
|
* <li>This is accomplished by passing the "export" SchemaAction to the
|
||||||
|
* MappingTool, and using the RETAIN_DATA option to prevent SQL commands
|
||||||
|
* from getting executed
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Tim McConnell
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public class TestDynamicSchemas extends SingleEMFTestCase {
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testDerbyDynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI derbyEMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:derby:net://host:1527/databaseName",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( derbyEMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testDB2DynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI db2EMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:db2://localhost:5000/db2",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( db2EMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testOracleDynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI oracleEMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:oracle:thin:@host:1234:database_sid",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( oracleEMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testAccessDynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI accessEMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:odbc:Driver=Microsoft Access Driver (*.mdb);DBQ=c:",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( accessEMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testSQLServerDynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI sqlserverEMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:microsoft:sqlserver:",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( sqlserverEMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testMySQLDynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI mysqlEMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:mysql://host1:1,host2:2/database?p1=v1&p2=v2",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( mysqlEMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testPostgresDynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI postgresEMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:postgresql:database",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( postgresEMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testInformixDynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI informixEMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:informix-sqli:",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( informixEMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testSybaseDynamicSchema() {
|
||||||
|
OpenJPAEntityManagerFactorySPI sybaseEMF =
|
||||||
|
createEMF(EntityVeryLongNames.class,
|
||||||
|
"openjpa.ConnectionURL",
|
||||||
|
"jdbc:sybase:Tds:host:1234?ServiceName=db",
|
||||||
|
"openjpa.jdbc.SynchronizeMappings", "export",
|
||||||
|
"openjpa.jdbc.SchemaFactory", "dynamic", RETAIN_DATA);
|
||||||
|
validateTableName( sybaseEMF );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void validateTableName(OpenJPAEntityManagerFactorySPI emf) {
|
||||||
|
JDBCConfiguration conf = (JDBCConfiguration) emf.getConfiguration();
|
||||||
|
DBDictionary dict = conf.getDBDictionaryInstance();
|
||||||
|
ClassMapping mapping = (ClassMapping)conf.
|
||||||
|
getMetaDataRepositoryInstance().
|
||||||
|
getMetaData(EntityVeryLongNames.class,getClass().
|
||||||
|
getClassLoader(), true);
|
||||||
|
Table table = mapping.getTable();
|
||||||
|
assertTrue(table.getName().length() > 0);
|
||||||
|
assertTrue(table.getName().length() <= dict.maxTableNameLength);
|
||||||
|
validateColumnNames(table, dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void validateColumnNames(Table table, DBDictionary dict) {
|
||||||
|
Column[] columns = table.getColumns();
|
||||||
|
for (Column column : columns) {
|
||||||
|
assertTrue(column.getName().length() > 0);
|
||||||
|
assertTrue(column.getName().length() <= dict.maxColumnNameLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue