org.babyfish.hibernate.persister.UncompletedInitializedProperties Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of babyfish-hibernate Show documentation
Show all versions of babyfish-hibernate Show documentation
The hibernate enhancement project of BabyFish.
The newest version!
/*
* BabyFish, Object Model Framework for Java and JPA.
* https://github.com/babyfish-ct/babyfish
*
* Copyright (c) 2008-2015, Tao Chen
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* Please visit "http://opensource.org/licenses/LGPL-3.0" to know more.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*/
package org.babyfish.hibernate.persister;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.NavigableSet;
import org.babyfish.collection.ArrayList;
import org.babyfish.collection.MACollections;
import org.babyfish.collection.TreeSet;
import org.babyfish.hibernate.model.loader.HibernateObjectModelScalarLoader;
import org.babyfish.lang.Nulls;
import org.babyfish.model.ObjectModel;
import org.babyfish.model.metadata.Property;
import org.babyfish.model.metadata.ScalarProperty;
import org.babyfish.persistence.model.metadata.JPAObjectModelMetadata;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;
/**
* @author Tao Chen
*/
class UncompletedInitializedProperties {
private UncompletedInitializedProperties() {
throw new UnsupportedOperationException();
}
static void update(
EntityPersisterBridge entityPersisterBridge,
Object[] state,
Object entity,
Serializable id,
Object rowId,
SessionImplementor session) {
FieldInterceptor fieldInterceptor = FieldInterceptionHelper.extractFieldInterceptor(entity);
if (!(fieldInterceptor instanceof HibernateObjectModelScalarLoader)) {
return;
}
HibernateObjectModelScalarLoader hibernateObjectModelScalarLoader =
(HibernateObjectModelScalarLoader)fieldInterceptor;
if (!hibernateObjectModelScalarLoader.isIncompletelyInitialized()) {
return;
}
ObjectModel objectModel = hibernateObjectModelScalarLoader.getObjectModel();
JPAObjectModelMetadata objectModelMetadata = objectModel.getObjectModelMetadata();
EntityPersister entityPersister = entityPersisterBridge.getEntityPersister();
String[] names = entityPersister.getPropertyNames();
Type[] types = entityPersister.getPropertyTypes();
boolean[] updateabilities = entityPersister.getPropertyUpdateability();
List updatePropertyIndexList = new ArrayList<>();
for (int propertyIndex = 0; propertyIndex < names.length; propertyIndex++) {
if (updateabilities[propertyIndex]) {
Property property = objectModelMetadata.getMappingSources().get(names[propertyIndex]);
if (property instanceof ScalarProperty) {
ScalarProperty scalarProperty = (ScalarProperty)property;
if (scalarProperty.isDeferrable()) {
int propertyId = scalarProperty.getId();
if (!objectModel.isDisabled(propertyId) && !objectModel.isUnloaded(propertyId)) {
updatePropertyIndexList.add(propertyIndex);
}
}
}
}
}
if (updatePropertyIndexList.isEmpty()) {
return;
}
int[] updatePropertyIndexes = new int[updatePropertyIndexList.size()];
for (int i = updatePropertyIndexList.size() - 1; i >= 0; i--) {
updatePropertyIndexes[i] = updatePropertyIndexList.get(i);
}
boolean[] tableUpdateNeeded = entityPersisterBridge.getTableUpdateNeeded(updatePropertyIndexes);
boolean[][] propertyColumnUpdateable = entityPersisterBridge.getPropertyColumnUpdateable();
for (int tableIndex = 0; tableIndex < entityPersisterBridge.getTableSpan(); tableIndex++) {
if (tableUpdateNeeded[tableIndex]) {
StringBuilder builder = new StringBuilder();
builder
.append("update ")
.append(entityPersisterBridge.getTableName(tableIndex))
.append(" set ");
boolean addComma = false;
for (int propertyIndex : updatePropertyIndexes) {
if (entityPersisterBridge.isPropertyOfTable(propertyIndex, tableIndex)) {
String[] columnNames = entityPersisterBridge.getPropertyColumnNames(propertyIndex);
for (int columnIndex = 0; columnIndex < columnNames.length; columnIndex++) {
if (propertyColumnUpdateable[propertyIndex][columnIndex]) {
if (addComma) {
builder.append(", ");
} else {
addComma = true;
}
builder.append(columnNames[columnIndex]).append(" = ?");
}
}
}
}
if (!addComma) {
continue;
}
builder.append(" where ");
addComma = false;
if (tableIndex == 0 && rowId != null) {
builder.append(entityPersisterBridge.getRowIdName()).append(" = ?");
} else {
for (String keyColumn : entityPersisterBridge.getKeyColumns(tableIndex)) {
if (addComma) {
builder.append(", ");
} else {
addComma = true;
}
builder.append(keyColumn).append(" = ?");
}
}
String sql = builder.toString();
JdbcCoordinator jdbcCoordinator = session.getTransactionCoordinator().getJdbcCoordinator();
PreparedStatement preparedStatement =
jdbcCoordinator
.getStatementPreparer()
.prepareStatement(sql);
try {
int paramIndex = 1;
for (int propertyIndex : updatePropertyIndexes) {
if (entityPersisterBridge.isPropertyOfTable(propertyIndex, tableIndex)) {
types[propertyIndex].nullSafeSet(
preparedStatement,
state[propertyIndex],
paramIndex,
propertyColumnUpdateable[propertyIndex],
session);
paramIndex += ArrayHelper.countTrue(propertyColumnUpdateable[propertyIndex]);
}
}
if (tableIndex == 0 && rowId != null) {
preparedStatement.setObject(paramIndex, rowId);
} else {
entityPersister.getIdentifierType().nullSafeSet(
preparedStatement,
id != null ? id : objectModel.getScalar(objectModelMetadata.getEntityIdProperty().getId()),
paramIndex,
session);
}
preparedStatement.executeUpdate();
} catch (SQLException ex) {
throw new HibernateException(ex);
} finally {
jdbcCoordinator.release(preparedStatement);
}
}
}
}
static int[] mergeDirty(int[] dirty, Object entity, Object[] currentState, Object[] previousState) {
FieldInterceptor fieldInterceptor = FieldInterceptionHelper.extractFieldInterceptor(entity);
if (!(fieldInterceptor instanceof HibernateObjectModelScalarLoader)) {
return dirty;
}
HibernateObjectModelScalarLoader hibernateObjectModelScalarLoader =
(HibernateObjectModelScalarLoader)fieldInterceptor;
if (!hibernateObjectModelScalarLoader.isDirty()) {
if (dirty != null) {
NavigableSet uset = null;
for (int dirtyIndex : dirty) {
if (previousState[dirtyIndex] == LazyPropertyInitializer.UNFETCHED_PROPERTY) {
if (uset == null) {
uset = new TreeSet<>();
}
uset.add(dirtyIndex);
}
}
if (uset != null) {
NavigableSet result = new TreeSet<>();
for (int dirtyIndex : dirty) {
result.add(dirtyIndex);
}
result.removeAll(uset);
if (result.isEmpty()) {
return null;
}
return MACollections.toIntArray(result);
}
}
return dirty;
}
NavigableSet set = null;
for (int i = currentState.length - 1; i >= 0; i--) {
if (currentState[i] != LazyPropertyInitializer.UNFETCHED_PROPERTY &&
previousState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY) {
if (set == null) {
set = new TreeSet<>();
}
set.add(i);
}
}
if (Nulls.isNullOrEmpty(set)) {
return dirty;
}
if (!Nulls.isNullOrEmpty(dirty)) {
for (int i : dirty) {
set.add(i);
}
}
if (set.isEmpty()) {
return null;
}
return MACollections.toIntArray(set);
}
interface EntityPersisterBridge {
EntityPersister getEntityPersister();
int getTableSpan();
String getTableName(int tableIndex);
boolean isPropertyOfTable(int propertyIndex, int tableIndex);
boolean[] getTableUpdateNeeded(int[] updatePropertyIndexes);
String getRowIdName();
String[] getKeyColumns(int tableIndex);
String[] getPropertyColumnNames(int propertyIndex);
boolean[][] getPropertyColumnUpdateable();
}
}