All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.mappings.structures.ObjectRelationalDataTypeDescriptor Maven / Gradle / Ivy

There is a newer version: 4.0.2
Show newest version
/*
 * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
package org.eclipse.persistence.mappings.structures;

import java.sql.Array;
import java.sql.Ref;
import java.sql.Struct;
import java.sql.Types;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.RelationalDescriptor;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.ValueReadQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;

/**
 * 

Purpose: * Differentiates object-relational descriptors from normal relational descriptors. * The object-relational descriptor describes a type not a table, (although there * is normally a table associated with the type, unless it is aggregate). */ @SuppressWarnings("unchecked") public class ObjectRelationalDataTypeDescriptor extends RelationalDescriptor { protected String structureName; protected Vector orderedFields; protected Vector allOrderedFields; public ObjectRelationalDataTypeDescriptor() { this.orderedFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(); } /** * INTERNAL: * Auto-Default orderedFields to fields */ @Override public void initialize(AbstractSession session) throws DescriptorException { super.initialize(session); if (orderedFields==null || orderedFields.size()==0){ orderedFields=getAllFields(); } setAllOrderedFields(); } /** * PUBLIC: * Order the fields in a specific * Add the field ordering, this will order the fields in the order this method is called. * @param fieldName the name of the field to add ordering on. */ public void addFieldOrdering(String fieldName) { getOrderedFields().addElement(new DatabaseField(fieldName)); } /** * INTERNAL: * Extract the direct values from the specified field value. * Return them in a vector. * The field value better be an Array. */ @Override public Vector buildDirectValuesFromFieldValue(Object fieldValue) throws DatabaseException { if(fieldValue == null) { return null; } return Helper.vectorFromArray((Object[])fieldValue); } /** * INTERNAL: * Build the appropriate field value for the specified * set of direct values. * The database better be expecting an ARRAY. */ @Override public Object buildFieldValueFromDirectValues(Vector directValues, String elementDataTypeName, AbstractSession session) throws DatabaseException { Object[] fields = Helper.arrayFromVector(directValues); try { ((DatabaseAccessor)session.getAccessor()).incrementCallCount(session); java.sql.Connection connection = ((DatabaseAccessor)session.getAccessor()).getConnection(); return session.getPlatform().createArray(elementDataTypeName, fields, session,connection); } catch (java.sql.SQLException ex) { throw DatabaseException.sqlException(ex, session, false); } finally { ((DatabaseAccessor)session.getAccessor()).decrementCallCount(); } } /** * INTERNAL: * Build and return the field value from the specified nested database row. * The database better be expecting a Struct. */ @Override public Object buildFieldValueFromNestedRow(AbstractRecord nestedRow, AbstractSession session) throws DatabaseException { java.sql.Connection connection = ((DatabaseAccessor)session.getAccessor()).getConnection(); return this.buildStructureFromRow(nestedRow, session, connection); } /** * INTERNAL: * Build and return the appropriate field value for the specified * set of nested rows. * The database better be expecting an ARRAY. * It looks like we can ignore inheritance here.... */ @Override public Object buildFieldValueFromNestedRows(Vector nestedRows, String structureName, AbstractSession session) throws DatabaseException { Object[] fields = new Object[nestedRows.size()]; java.sql.Connection connection = ((DatabaseAccessor)session.getAccessor()).getConnection(); boolean reconnected = false; try { if (connection == null) { ((DatabaseAccessor)session.getAccessor()).incrementCallCount(session); reconnected = true; connection = ((DatabaseAccessor)session.getAccessor()).getConnection(); } int i = 0; for (Enumeration stream = nestedRows.elements(); stream.hasMoreElements();) { AbstractRecord nestedRow = (AbstractRecord)stream.nextElement(); fields[i++] = this.buildStructureFromRow(nestedRow, session, connection); } return session.getPlatform().createArray(structureName, fields, session,connection); } catch (java.sql.SQLException exception) { throw DatabaseException.sqlException(exception, session, false); } finally { if (reconnected) { ((DatabaseAccessor)session.getAccessor()).decrementCallCount(); } } } /** * INTERNAL: * Build and return the nested rows from the specified field value. * This method allows the field value to be an ARRAY containing other structures * such as arrays or Struct, or direct values. */ static public Object buildContainerFromArray(Array fieldValue, ObjectRelationalDatabaseField arrayField, AbstractSession session) throws DatabaseException { if (arrayField.getType()==null){ return fieldValue; } Object[] objects = null; try { objects = (Object[])fieldValue.getArray(); } catch (java.sql.SQLException ex) { throw DatabaseException.sqlException(ex, session, false); } if (objects == null) { return null; } boolean isNestedStructure = false; ObjectRelationalDataTypeDescriptor ord=null; DatabaseField nestedType = null; nestedType = arrayField.getNestedTypeField(); if ((nestedType != null) && nestedType.getSqlType()==Types.STRUCT){ ClassDescriptor descriptor = session.getDescriptor(nestedType.getType()); if ((descriptor != null) && (descriptor.isObjectRelationalDataTypeDescriptor())) { //this is used to convert non-null objects passed through stored procedures and custom SQL to structs ord=(ObjectRelationalDataTypeDescriptor)descriptor; } } else if ((nestedType != null) && (nestedType instanceof ObjectRelationalDatabaseField) ){ isNestedStructure = true; } //handle ARRAY conversions ReadObjectQuery query = new ReadObjectQuery(); query.setSession(session); ContainerPolicy cp = ContainerPolicy.buildPolicyFor(arrayField.getType()); Object container = cp.containerInstance(objects.length); for (int i = 0; i < objects.length; i++) { Object arrayValue = objects[i]; if (arrayValue == null) { return null; } if (ord!=null){ AbstractRecord nestedRow = ord.buildRowFromStructure( (Struct)arrayValue); ClassDescriptor descriptor = ord; if (descriptor.hasInheritance()) { Class newElementClass = descriptor.getInheritancePolicy().classFromRow(nestedRow, session); if (!descriptor.getJavaClass().equals(newElementClass)) { descriptor = session.getDescriptor(newElementClass); if (descriptor==null){ descriptor=ord; } } } arrayValue = descriptor.getObjectBuilder().buildNewInstance(); descriptor.getObjectBuilder().buildAttributesIntoObject(arrayValue, null, nestedRow, query, null, null, false, session); } else if (isNestedStructure && (arrayValue instanceof Array)){ arrayValue = buildContainerFromArray((Array)arrayValue, (ObjectRelationalDatabaseField)nestedType, session); } cp.addInto(arrayValue, container, session); } return container; } /** * INTERNAL: * Build and return the nested database row from the specified field value. * The field value better be an Struct. */ @Override public AbstractRecord buildNestedRowFromFieldValue(Object fieldValue) throws DatabaseException { AbstractRecord row = new DatabaseRecord(); Object[] attributes = (Object[])fieldValue; for (int index = 0; index < getAllOrderedFields().size(); index++) { DatabaseField field = (DatabaseField) getAllOrderedFields().get(index); row.put(field, attributes[index]); } return row; } /** * INTERNAL: * Creates allOrderedFields Vector, keeping allFields contents ordered. */ private void setAllOrderedFields() { allOrderedFields = new Vector(orderedFields.size()); Vector allFieldsCopy = new Vector(getAllFields()); for (DatabaseField orderedField : (Vector) getOrderedFields()) { Iterator iterator = allFieldsCopy.iterator(); while (iterator.hasNext()) { DatabaseField field = iterator.next(); if (orderedField.getName().equalsIgnoreCase(field.getName())) { allOrderedFields.add(field); iterator.remove(); } } } } /** * INTERNAL: * Build and return the nested rows from the specified field value. * The field value better be an ARRAY. */ @Override public Vector buildNestedRowsFromFieldValue(Object fieldValue, AbstractSession session) throws DatabaseException { if(fieldValue==null){ return null; } Object[] structs = (Object[])fieldValue; Vector nestedRows = new Vector(structs.length); for (int i = 0; i < structs.length; i++) { Object[] struct = (Object[])structs[i]; if (struct == null) { return null; } nestedRows.addElement(this.buildNestedRowFromFieldValue(struct)); } return nestedRows; } /** * INTERNAL: * Build a row representation from the ADT structure field array. * TopLink will then build the object from the row. */ public AbstractRecord buildRowFromStructure(Struct structure) throws DatabaseException { Object[] attributes; try { attributes = structure.getAttributes(); } catch (java.sql.SQLException exception) { throw DatabaseException.sqlException(exception); } if(attributes!=null){ for(int i=0;i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy