
org.bridje.orm.impl.EntityContextImpl Maven / Gradle / Ivy
/*
* Copyright 2016 Bridje Framework.
*
* Licensed 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.bridje.orm.impl;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.bridje.orm.EntityContext;
import org.bridje.orm.Query;
import org.bridje.orm.SQLDialect;
import org.bridje.orm.Table;
import org.bridje.orm.TableColumn;
import org.bridje.orm.impl.sql.DeleteBuilder;
import org.bridje.orm.impl.sql.InsertBuilder;
import org.bridje.orm.impl.sql.SelectBuilder;
import org.bridje.orm.impl.sql.UpdateBuilder;
class EntityContextImpl implements EntityContext
{
private static final Logger LOG = Logger.getLogger(EntityContextImpl.class.getName());
private final DataSource ds;
private final EntitysCache cache;
private final SQLDialect dialect;
private final OrmServiceImpl orm;
public EntityContextImpl(OrmServiceImpl orm, DataSource ds, SQLDialect dialect)
{
this.orm = orm;
this.ds = ds;
this.cache = new EntitysCache();
this.dialect = dialect;
}
@Override
public void fixTable(Table>... tables) throws SQLException
{
if (tables != null)
{
for (Table> table : tables)
{
LOG.log(Level.INFO, "Checking table {0}", table.getName());
if (tableExists(table))
{
fixColumns(table);
}
else
{
createTable(table);
}
}
}
}
public T find(Class entity, Object id) throws SQLException
{
return find(orm.findTable(entity), id);
}
@Override
public T find(Table table, Object id) throws SQLException
{
if(id == null) return null;
TableImpl tableImpl = (TableImpl) table;
T cachedEntity = cache.get(tableImpl.getEntity(), id);
if (cachedEntity != null) return cachedEntity;
SelectBuilder qb = new SelectBuilder(dialect);
qb.select(tableImpl.allFieldsCommaSep())
.from(dialect.identifier(tableImpl.getName()))
.where(tableImpl.buildIdCondition())
.limit(0, 1);
Object serializedId = ((TableColumnImpl) table.getKey()).serialize(id);
return doQuery(qb.toString(), (rs) -> tableImpl.parse(rs), serializedId);
}
@Override
public T refresh(T entity) throws SQLException
{
TableImpl table = (TableImpl) orm.findTable(entity.getClass());
SelectBuilder qb = new SelectBuilder(dialect);
qb.select(table.allFieldsCommaSep())
.from(dialect.identifier(table.getName()))
.where(table.buildIdCondition())
.limit(0, 1);
Object id = ((TableColumnImpl) table.getKey()).getQueryParameter(entity);
return doQuery(qb.toString(), (rs) -> table.parse(entity, rs), id);
}
@Override
public T insert(T entity) throws SQLException
{
TableImpl table = orm.findTable((Class) entity.getClass());
InsertBuilder ib = new InsertBuilder();
ib.insertInto(dialect.identifier(table.getName()))
.fields(table.nonAiFieldsCommaSepNoTable())
.valuesParams(table.getNonAiColumns().size());
if (table.getKey().isAutoIncrement())
{
doUpdate(ib.toString(),
rs -> table.updateKeyField(entity, rs),
table.buildInsertParameters(entity));
}
else
{
doUpdate(ib.toString(), table.buildInsertParameters(entity));
}
cache.put(entity, table.findKeyValue(entity));
return entity;
}
@Override
public T update(T entity) throws SQLException
{
return update(entity, null);
}
@Override
public T update(T entity, Object id) throws SQLException
{
TableImpl table = orm.findTable((Class) entity.getClass());
UpdateBuilder ub = new UpdateBuilder(dialect);
ub.update(dialect.identifier(table.getName()));
table.nonAiFieldsStream(dialect.identifier(table.getName()) + ".").forEach(ub::set);
ub.where(table.buildIdCondition());
Object updateId = id;
if (updateId == null) updateId = table.findKeyValue(entity);
Object serializedId = ((TableColumnImpl) table.getKey()).serialize(updateId);
doUpdate(ub.toString(), table.buildUpdateParameters(entity, serializedId));
cache.remove(entity.getClass(), updateId);
cache.put(entity, id);
return entity;
}
@Override
public T delete(T entity) throws SQLException
{
TableImpl table = orm.findTable((Class) entity.getClass());
DeleteBuilder db = new DeleteBuilder();
db.delete(dialect.identifier(table.getName())).where(table.buildIdCondition());
Object updateId = table.findKeyValue(entity);
if (updateId != null)
{
Object serializedId = ((TableColumnImpl) table.getKey()).serialize(updateId);
doUpdate(db.toString(), serializedId);
cache.remove(entity.getClass(), updateId);
}
return entity;
}
public T doQuery(String query, QueryConsumer consumer, Object... parameters) throws SQLException
{
T result;
try (Connection conn = ds.getConnection())
{
if(conn == null) throw new SQLException("Could not create a new connection with the database.");
try(PreparedStatement stmt = conn.prepareStatement(query))
{
for (int i = 0; i < parameters.length; i++)
{
setParam(stmt, parameters[i], i + 1);
}
try (ResultSet resultSet = stmt.executeQuery())
{
result = consumer.parse(resultSet);
}
}
}
catch (SQLException e)
{
LOG.log(Level.SEVERE, "Invalid Query: {0}", query);
throw e;
}
return result;
}
public T doUpdate(String query, QueryConsumer consumer, Object... parameters) throws SQLException
{
T result = null;
try (Connection conn = ds.getConnection(); PreparedStatement stmt = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS))
{
for (int i = 0; i < parameters.length; i++)
{
setParam(stmt, parameters[i], i + 1);
}
if (stmt.executeUpdate() > 0)
{
try (ResultSet rs = stmt.getGeneratedKeys())
{
result = consumer.parse(rs);
}
}
}
catch (SQLException e)
{
LOG.log(Level.SEVERE, "Invalid Query: {0}", query);
throw e;
}
return result;
}
public int doUpdate(String query, Object... parameters) throws SQLException
{
try (Connection conn = ds.getConnection(); PreparedStatement stmt = conn.prepareStatement(query))
{
for (int i = 0; i < parameters.length; i++)
{
setParam(stmt, parameters[i], i + 1);
}
return stmt.executeUpdate();
}
catch (SQLException e)
{
LOG.log(Level.SEVERE, "Invalid Query: {0}", query);
throw e;
}
}
private boolean tableExists(Table table) throws SQLException
{
try (Connection conn = ds.getConnection())
{
DatabaseMetaData metaData = conn.getMetaData();
try (ResultSet resultSet = metaData.getTables(null, null, table.getName(), null))
{
if (resultSet.next()) return true;
}
}
return false;
}
private void fixColumns(Table table) throws SQLException
{
List> fields = table.getColumns();
for (TableColumn field : fields)
{
fixColumn(field);
}
List columnNames = findColumnNames(table.getName());
for (String columnName : columnNames)
{
TableColumn tbCol = table.findColumnByName(columnName);
if (tbCol == null)
{
LOG.log(Level.WARNING, "Column {0} of table {1} no longer exists in the model.", new Object[]{ columnName, table.getName()});
}
}
}
private void fixIndexs(Table table) throws SQLException
{
List> fields = table.getColumns();
for (TableColumn field : fields)
{
fixIndex(field);
}
}
private void fixColumn(TableColumn column) throws SQLException
{
if (!columnExists(column.getTable().getName(), column.getName()))
{
String query = dialect.createColumn(column);
LOG.log(Level.INFO, "Creating Column: \n{0}", query);
doUpdate(query);
}
}
private void fixIndex(TableColumn column) throws SQLException
{
if (column.isIndexed() && !indexExists(column.getTable().getName(), column.getName()))
{
String query = dialect.createIndex(column);
LOG.log(Level.INFO, "Creating Index: \n{0}", query);
doUpdate(query);
}
}
private boolean columnExists(String tableName, String columnName) throws SQLException
{
try (Connection conn = ds.getConnection())
{
DatabaseMetaData metaData = conn.getMetaData();
try (ResultSet resultSet = metaData.getColumns(null, null, tableName, columnName))
{
if (resultSet.next()) return true;
}
}
return false;
}
private List findColumnNames(String tableName) throws SQLException
{
List result = new ArrayList<>();
try (Connection conn = ds.getConnection())
{
DatabaseMetaData metaData = conn.getMetaData();
try (ResultSet resultSet = metaData.getColumns(null, null, tableName, null))
{
while (resultSet.next())
{
result.add(resultSet.getString("COLUMN_NAME"));
}
}
}
return result;
}
private boolean indexExists(String tableName, String columnName) throws SQLException
{
try (Connection conn = ds.getConnection())
{
DatabaseMetaData metaData = conn.getMetaData();
try (ResultSet resultSet = metaData.getIndexInfo(null, null, tableName, false, true))
{
while (resultSet.next())
{
String col = resultSet.getString("COLUMN_NAME");
if (col != null && col.equalsIgnoreCase(columnName))
{
return true;
}
}
}
}
return false;
}
private void createTable(Table table) throws SQLException
{
String query = dialect.createTable(table);
LOG.log(Level.INFO, "Creating Table: \n{0}", query);
doUpdate(query);
fixIndexs(table);
}
@Override
public Query query(Table table)
{
return new QueryImpl<>(this, (TableImpl) table);
}
private void setParam(PreparedStatement stmt, Object parameter, int index) throws SQLException
{
if (parameter instanceof Character)
{
stmt.setString(index, parameter.toString());
}
else
{
stmt.setObject(index, parameter);
}
}
public EntitysCache getEnittysCache()
{
return cache;
}
@Override
public void clearCache()
{
cache.clear();
}
@Override
public SQLDialect getDialect()
{
return dialect;
}
@Override
public Table findTable(Class entity)
{
return orm.findTable(entity);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy