mirror of
https://github.com/Rogiel/l2jserver2
synced 2025-12-05 23:22:47 +00:00
Implements insert and update mappers
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||
*
|
||||
* l2jserver2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* l2jserver2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with l2jserver2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.service.database.dao;
|
||||
|
||||
import com.l2jserver.model.id.ID;
|
||||
import com.mysema.query.sql.RelationalPathBase;
|
||||
import com.mysema.query.types.Path;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
* @param <O>
|
||||
* the object type
|
||||
* @param <R>
|
||||
* the raw id type
|
||||
* @param <I>
|
||||
* the id type
|
||||
* @param <E>
|
||||
* the table type
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractMapper<O, R, I extends ID<? super R>, E extends RelationalPathBase<R>>
|
||||
implements SelectMapper<O, R, I, E>, UpdateMapper<O, E>,
|
||||
InsertMapper<O, R, I, E> {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SelectMapper<I, R, I, E> getIDMapper(E entity) {
|
||||
return new SelectPrimaryKeyMapper<R, I, E>(getPrimaryKeyMapper(),
|
||||
(Path<R>) entity.getPrimaryKey().getLocalColumns().get(0));
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,21 @@ import com.mysema.query.types.Path;
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public interface DatabaseRow {
|
||||
/**
|
||||
* @param <T>
|
||||
* the path type
|
||||
* @param path
|
||||
* the path
|
||||
* @return the value associated in the row for the given {@link Path}
|
||||
*/
|
||||
<T> T get(Path<T> path);
|
||||
|
||||
|
||||
/**
|
||||
* @param <T>
|
||||
* the path type
|
||||
* @param path
|
||||
* the path
|
||||
* @return <code>true</code> if the path has a <code>null</code> value
|
||||
*/
|
||||
<T> boolean isNull(Path<T> path);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||
*
|
||||
* l2jserver2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* l2jserver2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with l2jserver2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.service.database.dao;
|
||||
|
||||
import com.l2jserver.model.id.ID;
|
||||
import com.mysema.query.sql.RelationalPathBase;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
* @param <O>
|
||||
* the object type
|
||||
* @param <R>
|
||||
* the raw id type
|
||||
* @param <I>
|
||||
* the id type
|
||||
* @param <E>
|
||||
* the table type
|
||||
*/
|
||||
public interface InsertMapper<O, R, I extends ID<? super R>, E extends RelationalPathBase<?>> {
|
||||
/**
|
||||
* Maps the insert values to the <code>row</code>
|
||||
*
|
||||
* @param e
|
||||
* the database table
|
||||
* @param object
|
||||
* the object to be mapped
|
||||
* @param row
|
||||
* the row to be mapped
|
||||
*/
|
||||
void insert(E e, O object, WritableDatabaseRow row);
|
||||
|
||||
/**
|
||||
* @return the {@link PrimaryKeyMapper} that maps {@link ID}s that will be
|
||||
* used for caches
|
||||
*/
|
||||
PrimaryKeyMapper<I, R> getPrimaryKeyMapper();
|
||||
}
|
||||
@@ -16,15 +16,22 @@
|
||||
*/
|
||||
package com.l2jserver.service.database.dao;
|
||||
|
||||
import com.mysema.query.sql.RelationalPathBase;
|
||||
import com.l2jserver.model.id.ID;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
* @param <O>
|
||||
* @param <I>
|
||||
* the object type returned by this mapper
|
||||
* @param <E>
|
||||
* the entity type
|
||||
* @param <R>
|
||||
* the ID raw type
|
||||
*/
|
||||
public interface Mapper<O, E extends RelationalPathBase<?>> {
|
||||
O map(E entity, DatabaseRow row);
|
||||
public interface PrimaryKeyMapper<I extends ID<? super R>, R> {
|
||||
/**
|
||||
* Reads the ID as an object
|
||||
*
|
||||
* @param raw
|
||||
* the raw id
|
||||
* @return the {@link ID} object
|
||||
*/
|
||||
I createID(R raw);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||
*
|
||||
* l2jserver2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* l2jserver2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with l2jserver2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.service.database.dao;
|
||||
|
||||
import com.l2jserver.model.id.ID;
|
||||
import com.mysema.query.sql.RelationalPathBase;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
* @param <O>
|
||||
* the object type
|
||||
* @param <R>
|
||||
* the raw id type
|
||||
* @param <I>
|
||||
* the id type
|
||||
* @param <E>
|
||||
* the table type
|
||||
*/
|
||||
public interface SelectMapper<O, R, I extends ID<? super R>, E extends RelationalPathBase<R>> {
|
||||
/**
|
||||
* Reads the {@link DatabaseRow} object into an model object
|
||||
*
|
||||
* @param entity
|
||||
* the entity object (used to execute the select query)
|
||||
* @param row
|
||||
* the database row containing data
|
||||
* @return the created object
|
||||
*/
|
||||
O select(E entity, DatabaseRow row);
|
||||
|
||||
/**
|
||||
* @param entity
|
||||
* the table
|
||||
* @return an wrapper {@link PrimaryKeyMapper} that maps results into
|
||||
* {@link ID}s instead of objects
|
||||
*/
|
||||
SelectMapper<I, R, I, E> getIDMapper(E entity);
|
||||
|
||||
/**
|
||||
* @return the {@link PrimaryKeyMapper} that maps {@link ID}s that will be
|
||||
* used for caches
|
||||
*/
|
||||
PrimaryKeyMapper<I, R> getPrimaryKeyMapper();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||
*
|
||||
* l2jserver2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* l2jserver2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with l2jserver2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.service.database.dao;
|
||||
|
||||
import com.l2jserver.model.id.ID;
|
||||
import com.mysema.query.sql.RelationalPathBase;
|
||||
import com.mysema.query.types.Path;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
* @param <R>
|
||||
* the primary key raw type
|
||||
* @param <I>
|
||||
* the ID type
|
||||
* @param <E>
|
||||
* the table type
|
||||
*/
|
||||
public class SelectPrimaryKeyMapper<R, I extends ID<? super R>, E extends RelationalPathBase<R>>
|
||||
implements SelectMapper<I, R, I, E> {
|
||||
private final PrimaryKeyMapper<I, R> mapper;
|
||||
private final Path<R> path;
|
||||
|
||||
/**
|
||||
* @param mapper
|
||||
* the {@link PrimaryKeyMapper}
|
||||
* @param path
|
||||
* the {@link Path} to the primary key
|
||||
*/
|
||||
public SelectPrimaryKeyMapper(PrimaryKeyMapper<I, R> mapper, Path<R> path) {
|
||||
this.mapper = mapper;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public I select(E entity, DatabaseRow row) {
|
||||
return mapper.createID(row.get(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectMapper<I, R, I, E> getIDMapper(E entity) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimaryKeyMapper<I, R> getPrimaryKeyMapper() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||
*
|
||||
* l2jserver2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* l2jserver2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with l2jserver2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.service.database.dao;
|
||||
|
||||
import com.mysema.query.sql.RelationalPathBase;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
* @param <O>
|
||||
* the object type returned by this mapper
|
||||
* @param <E>
|
||||
* the entity type
|
||||
*/
|
||||
public interface UpdateMapper<O, E extends RelationalPathBase<?>> {
|
||||
/**
|
||||
* Maps the update values to the <code>row</code>
|
||||
*
|
||||
* @param e
|
||||
* the database table
|
||||
* @param object
|
||||
* the object to be mapped
|
||||
* @param row
|
||||
* the row to be mapped
|
||||
*/
|
||||
void update(E e, O object, WritableDatabaseRow row);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||
*
|
||||
* l2jserver2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* l2jserver2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with l2jserver2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.service.database.dao;
|
||||
|
||||
import com.mysema.query.types.Path;
|
||||
|
||||
/**
|
||||
* Database column used to read data
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public interface WritableDatabaseRow {
|
||||
/**
|
||||
* @param <T>
|
||||
* the path type
|
||||
* @param path
|
||||
* the path
|
||||
* @param value
|
||||
* the value to be set
|
||||
* @return this instance
|
||||
*/
|
||||
<T> WritableDatabaseRow set(Path<T> path, T value);
|
||||
|
||||
/**
|
||||
* @param <T>
|
||||
* the path type
|
||||
* @param path
|
||||
* the path to be setted to <code>null</code>
|
||||
* @return this instance
|
||||
*/
|
||||
<T> WritableDatabaseRow setNull(Path<T> path);
|
||||
}
|
||||
@@ -61,7 +61,9 @@ import com.l2jserver.service.database.DataAccessObject;
|
||||
import com.l2jserver.service.database.DatabaseException;
|
||||
import com.l2jserver.service.database.DatabaseService;
|
||||
import com.l2jserver.service.database.dao.DatabaseRow;
|
||||
import com.l2jserver.service.database.dao.Mapper;
|
||||
import com.l2jserver.service.database.dao.InsertMapper;
|
||||
import com.l2jserver.service.database.dao.SelectMapper;
|
||||
import com.l2jserver.service.database.dao.UpdateMapper;
|
||||
import com.l2jserver.service.database.sql.ddl.QueryFactory;
|
||||
import com.l2jserver.service.database.sql.ddl.TableFactory;
|
||||
import com.l2jserver.service.database.sql.ddl.struct.Table;
|
||||
@@ -70,7 +72,6 @@ import com.mysema.query.sql.AbstractSQLQuery;
|
||||
import com.mysema.query.sql.RelationalPathBase;
|
||||
import com.mysema.query.sql.SQLQueryFactory;
|
||||
import com.mysema.query.sql.dml.SQLDeleteClause;
|
||||
import com.mysema.query.sql.dml.SQLInsertClause;
|
||||
import com.mysema.query.sql.dml.SQLUpdateClause;
|
||||
import com.mysema.query.sql.types.Type;
|
||||
import com.mysema.query.types.Path;
|
||||
@@ -88,9 +89,9 @@ import com.mysema.query.types.Path;
|
||||
* you do need low level access, feel free to use the {@link Query} class
|
||||
* directly.
|
||||
*
|
||||
* <h2>The {@link Mapper} object</h2>
|
||||
* <h2>The {@link SelectMapper} object</h2>
|
||||
*
|
||||
* The {@link Mapper} object maps an JDBC {@link DatabaseRow} into an Java
|
||||
* The {@link SelectMapper} object maps an JDBC {@link DatabaseRow} into an Java
|
||||
* {@link Object}.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
@@ -237,7 +238,7 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
*/
|
||||
@ConfigurationPropertyGetter(defaultValue = "true")
|
||||
@ConfigurationXPath("/configuration/services/database/jdbc/updateSchema")
|
||||
String getUpdateSchema();
|
||||
boolean getUpdateSchema();
|
||||
|
||||
/**
|
||||
* @param updateSchema
|
||||
@@ -245,7 +246,7 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
*/
|
||||
@ConfigurationPropertySetter
|
||||
@ConfigurationXPath("/configuration/services/database/jdbc/updateSchema")
|
||||
void setUpdateSchema(String updateSchema);
|
||||
void setUpdateSchema(boolean updateSchema);
|
||||
|
||||
/**
|
||||
* @return the maximum number of active connections
|
||||
@@ -345,16 +346,18 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
true);
|
||||
dataSource = new PoolingDataSource(connectionPool);
|
||||
|
||||
try {
|
||||
final Connection conn = dataSource.getConnection();
|
||||
if (config.getUpdateSchema()) {
|
||||
try {
|
||||
ensureDatabaseSchema(conn);
|
||||
} finally {
|
||||
conn.close();
|
||||
final Connection conn = dataSource.getConnection();
|
||||
try {
|
||||
ensureDatabaseSchema(conn);
|
||||
} finally {
|
||||
conn.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServiceStartException(
|
||||
"Couldn't update database schema", e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServiceStartException("Couldn't update database schema",
|
||||
e);
|
||||
}
|
||||
|
||||
for (final Type<?> type : sqlTypes) {
|
||||
@@ -570,7 +573,8 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
conn.setAutoCommit(false);
|
||||
}
|
||||
try {
|
||||
return query.query(engine.createSQLQueryFactory(conn));
|
||||
return query
|
||||
.query(engine.createSQLQueryFactory(conn), this);
|
||||
} finally {
|
||||
if (!inTransaction) {
|
||||
conn.commit();
|
||||
@@ -659,9 +663,12 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
*
|
||||
* @param factory
|
||||
* the query factory (database specific)
|
||||
* @param database
|
||||
* the database service instance
|
||||
* @return the query return value
|
||||
*/
|
||||
R query(SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory);
|
||||
R query(SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory,
|
||||
DatabaseService database);
|
||||
}
|
||||
|
||||
public static abstract class AbstractQuery<R> implements Query<R> {
|
||||
@@ -674,24 +681,29 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class InsertQuery<O, E extends RelationalPathBase<?>, K>
|
||||
public static class InsertQuery<O, RI, I extends ID<? super RI>, E extends RelationalPathBase<?>>
|
||||
extends AbstractQuery<Integer> {
|
||||
private final InsertMapper<O, RI, I, E> mapper;
|
||||
private final Iterator<O> iterator;
|
||||
private final Path<K> primaryKey;
|
||||
private final Path<RI> primaryKey;
|
||||
|
||||
protected final E e;
|
||||
|
||||
/**
|
||||
* @param entity
|
||||
* the entity type
|
||||
* @param mapper
|
||||
* the insert mapper
|
||||
* @param iterator
|
||||
* the objects to be inserted
|
||||
* @param primaryKey
|
||||
* the primary key, if any. Only required if the ID is
|
||||
* generated by the database engine.
|
||||
*/
|
||||
public InsertQuery(E entity, Path<K> primaryKey, Iterator<O> iterator) {
|
||||
public InsertQuery(E entity, InsertMapper<O, RI, I, E> mapper,
|
||||
Path<RI> primaryKey, Iterator<O> iterator) {
|
||||
this.iterator = iterator;
|
||||
this.mapper = mapper;
|
||||
this.e = entity;
|
||||
this.primaryKey = primaryKey;
|
||||
}
|
||||
@@ -699,27 +711,35 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
/**
|
||||
* @param entity
|
||||
* the entity type
|
||||
* @param mapper
|
||||
* the insert mapper
|
||||
* @param iterator
|
||||
* the objects to be inserted
|
||||
*/
|
||||
public InsertQuery(E entity, Iterator<O> iterator) {
|
||||
this(entity, null, iterator);
|
||||
public InsertQuery(E entity, InsertMapper<O, RI, I, E> mapper,
|
||||
Iterator<O> iterator) {
|
||||
this(entity, mapper, null, iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entity
|
||||
* the entity type
|
||||
* @param mapper
|
||||
* the insert mapper
|
||||
* @param objects
|
||||
* the objects to be inserted
|
||||
*/
|
||||
@SafeVarargs
|
||||
public InsertQuery(E entity, O... objects) {
|
||||
this(entity, null, Iterators.forArray(objects));
|
||||
public InsertQuery(E entity, InsertMapper<O, RI, I, E> mapper,
|
||||
O... objects) {
|
||||
this(entity, mapper, null, Iterators.forArray(objects));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entity
|
||||
* the entity type
|
||||
* @param mapper
|
||||
* the insert mapper
|
||||
* @param objects
|
||||
* the objects to be inserted
|
||||
* @param primaryKey
|
||||
@@ -727,25 +747,31 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
* generated by the database engine.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public InsertQuery(E entity, Path<K> primaryKey, O... objects) {
|
||||
this(entity, primaryKey, Iterators.forArray(objects));
|
||||
public InsertQuery(E entity, InsertMapper<O, RI, I, E> mapper,
|
||||
Path<RI> primaryKey, O... objects) {
|
||||
this(entity, mapper, primaryKey, Iterators.forArray(objects));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final Integer query(
|
||||
SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory) {
|
||||
SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory,
|
||||
DatabaseService database) {
|
||||
int rows = 0;
|
||||
while (iterator.hasNext()) {
|
||||
final O object = iterator.next();
|
||||
final SQLInsertClause insert = factory.insert(e);
|
||||
// maps query to the values
|
||||
map(insert, object);
|
||||
final SQLInsertWritableDatabaseRow row = new SQLInsertWritableDatabaseRow(
|
||||
factory.insert(e));
|
||||
mapper.insert(e, object, row);
|
||||
|
||||
if (primaryKey == null) {
|
||||
insert.execute();
|
||||
row.getClause().execute();
|
||||
} else {
|
||||
final K key = insert.executeWithKey(primaryKey);
|
||||
key(key, object);
|
||||
final RI key = row.getClause().executeWithKey(primaryKey);
|
||||
final I id = mapper.getPrimaryKeyMapper().createID(key);
|
||||
if (object instanceof Model) {
|
||||
((Model<I>) object).setID(id);
|
||||
}
|
||||
}
|
||||
rows++;
|
||||
|
||||
@@ -753,52 +779,56 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
protected abstract void map(SQLInsertClause q, O o);
|
||||
|
||||
protected void key(K k, O o) {
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class UpdateQuery<O, E extends RelationalPathBase<?>>
|
||||
extends AbstractQuery<Integer> {
|
||||
private final UpdateMapper<O, E> mapper;
|
||||
private final Iterator<O> iterator;
|
||||
protected final E e;
|
||||
|
||||
/**
|
||||
* @param entity
|
||||
* the entity type
|
||||
* @param mapper
|
||||
* the update mapper
|
||||
* @param iterator
|
||||
* the objects to be inserted
|
||||
*/
|
||||
public UpdateQuery(E entity, Iterator<O> iterator) {
|
||||
public UpdateQuery(E entity, UpdateMapper<O, E> mapper,
|
||||
Iterator<O> iterator) {
|
||||
this.iterator = iterator;
|
||||
this.mapper = mapper;
|
||||
this.e = entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entity
|
||||
* the entity type
|
||||
* @param mapper
|
||||
* the update mapper
|
||||
* @param objects
|
||||
* the objects to be inserted
|
||||
*/
|
||||
@SafeVarargs
|
||||
public UpdateQuery(E entity, O... objects) {
|
||||
this(entity, Iterators.forArray(objects));
|
||||
public UpdateQuery(E entity, UpdateMapper<O, E> mapper, O... objects) {
|
||||
this(entity, mapper, Iterators.forArray(objects));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Integer query(
|
||||
SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory) {
|
||||
SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory,
|
||||
DatabaseService database) {
|
||||
int rows = 0;
|
||||
while (iterator.hasNext()) {
|
||||
final O object = iterator.next();
|
||||
final SQLUpdateClause update = factory.update(e);
|
||||
final SQLUpdateWritableDatabaseRow row = new SQLUpdateWritableDatabaseRow(
|
||||
factory.update(e));
|
||||
// maps query to the values
|
||||
query(update, object);
|
||||
map(update, object);
|
||||
query(row.getClause(), object);
|
||||
mapper.update(e, object, row);
|
||||
|
||||
rows += update.execute();
|
||||
rows += row.getClause().execute();
|
||||
|
||||
updateDesire(object, ObjectDesire.UPDATE);
|
||||
}
|
||||
@@ -806,8 +836,6 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
}
|
||||
|
||||
protected abstract void query(SQLUpdateClause q, O o);
|
||||
|
||||
protected abstract void map(SQLUpdateClause q, O o);
|
||||
}
|
||||
|
||||
public static abstract class DeleteQuery<O, E extends RelationalPathBase<?>>
|
||||
@@ -839,7 +867,8 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
|
||||
@Override
|
||||
public final Integer query(
|
||||
SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory) {
|
||||
SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory,
|
||||
DatabaseService database) {
|
||||
int rows = 0;
|
||||
while (iterator.hasNext()) {
|
||||
final O object = iterator.next();
|
||||
@@ -857,10 +886,10 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
protected abstract void query(SQLDeleteClause q, O o);
|
||||
}
|
||||
|
||||
public static abstract class AbstractSelectQuery<R, O, E extends RelationalPathBase<?>>
|
||||
public static abstract class AbstractSelectQuery<R, O, RI, I extends ID<? super RI>, E extends RelationalPathBase<RI>>
|
||||
extends AbstractQuery<R> {
|
||||
protected final E entity;
|
||||
protected final Mapper<O, E> mapper;
|
||||
protected final SelectMapper<O, RI, I, E> mapper;
|
||||
|
||||
/**
|
||||
* @param entity
|
||||
@@ -868,70 +897,107 @@ public abstract class AbstractSQLDatabaseService extends AbstractService
|
||||
* @param mapper
|
||||
* the object mapper
|
||||
*/
|
||||
public AbstractSelectQuery(E entity, Mapper<O, E> mapper) {
|
||||
public AbstractSelectQuery(E entity, SelectMapper<O, RI, I, E> mapper) {
|
||||
this.entity = entity;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final R query(
|
||||
SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory) {
|
||||
SQLQueryFactory<? extends AbstractSQLQuery<?>, ?, ?, ?, ?, ?> factory,
|
||||
DatabaseService database) {
|
||||
final AbstractSQLQuery<?> select = factory.query();
|
||||
// maps query to the values
|
||||
select.from(entity);
|
||||
query(select, entity);
|
||||
return perform(select);
|
||||
return perform(select, database);
|
||||
}
|
||||
|
||||
protected abstract void query(AbstractSQLQuery<?> q, E e);
|
||||
|
||||
protected abstract R perform(AbstractSQLQuery<?> select);
|
||||
protected abstract R perform(AbstractSQLQuery<?> select,
|
||||
DatabaseService database);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected O lookupCache(DatabaseRow row, DatabaseService database) {
|
||||
final I id = mapper.getPrimaryKeyMapper().createID(
|
||||
(RI) row.get(entity.getPrimaryKey().getLocalColumns()
|
||||
.get(0)));
|
||||
|
||||
if (id != null) {
|
||||
if (database.hasCachedObject(id))
|
||||
return (O) database.getCachedObject(id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void updateCache(O instance, DatabaseService database) {
|
||||
if (instance == null)
|
||||
return;
|
||||
if (instance instanceof Model)
|
||||
database.updateCache(((Model<?>) instance).getID(),
|
||||
(Model<?>) instance);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class SelectSingleQuery<O, E extends RelationalPathBase<?>>
|
||||
extends AbstractSelectQuery<O, O, E> {
|
||||
public static abstract class SelectSingleQuery<O, RI, I extends ID<? super RI>, E extends RelationalPathBase<RI>>
|
||||
extends AbstractSelectQuery<O, O, RI, I, E> {
|
||||
/**
|
||||
* @param entity
|
||||
* the entity
|
||||
* @param mapper
|
||||
* the mapper
|
||||
*/
|
||||
public SelectSingleQuery(E entity, Mapper<O, E> mapper) {
|
||||
public SelectSingleQuery(E entity, SelectMapper<O, RI, I, E> mapper) {
|
||||
super(entity, mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final O perform(AbstractSQLQuery<?> select) {
|
||||
protected final O perform(AbstractSQLQuery<?> select,
|
||||
DatabaseService database) {
|
||||
final List<Object[]> results = select.limit(1).list(entity.all());
|
||||
if (results.size() == 1) {
|
||||
return mapper.map(entity, new SQLDatabaseRow(results.get(0),
|
||||
entity));
|
||||
final DatabaseRow row = new SQLDatabaseRow(results.get(0),
|
||||
entity);
|
||||
O object = lookupCache(row, database);
|
||||
if (object == null) {
|
||||
object = mapper.select(entity,
|
||||
new SQLDatabaseRow(results.get(0), entity));
|
||||
updateCache(object, database);
|
||||
}
|
||||
return object;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class SelectListQuery<O, E extends RelationalPathBase<?>>
|
||||
extends AbstractSelectQuery<List<O>, O, E> {
|
||||
public static abstract class SelectListQuery<O, RI, I extends ID<? super RI>, E extends RelationalPathBase<RI>>
|
||||
extends AbstractSelectQuery<List<O>, O, RI, I, E> {
|
||||
/**
|
||||
* @param entity
|
||||
* the entity
|
||||
* @param mapper
|
||||
* the mapper
|
||||
*/
|
||||
public SelectListQuery(E entity, Mapper<O, E> mapper) {
|
||||
public SelectListQuery(E entity, SelectMapper<O, RI, I, E> mapper) {
|
||||
super(entity, mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final List<O> perform(AbstractSQLQuery<?> select) {
|
||||
protected final List<O> perform(AbstractSQLQuery<?> select,
|
||||
DatabaseService database) {
|
||||
final List<Object[]> results = select.list(entity.all());
|
||||
final SQLDatabaseRow row = new SQLDatabaseRow(entity);
|
||||
final List<O> objects = CollectionFactory.newList();
|
||||
for (final Object[] data : results) {
|
||||
row.setRow(data);
|
||||
final O object = mapper.map(entity, row);
|
||||
|
||||
O object = lookupCache(row, database);
|
||||
if (object == null) {
|
||||
object = mapper.select(entity, row);
|
||||
updateCache(object, database);
|
||||
}
|
||||
if (object != null)
|
||||
objects.add(object);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||
*
|
||||
* l2jserver2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* l2jserver2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with l2jserver2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.service.database.sql;
|
||||
|
||||
import com.l2jserver.service.database.dao.WritableDatabaseRow;
|
||||
import com.mysema.query.sql.dml.SQLInsertClause;
|
||||
import com.mysema.query.types.Path;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*
|
||||
*/
|
||||
public class SQLInsertWritableDatabaseRow implements WritableDatabaseRow {
|
||||
/**
|
||||
* The SQL <code>INSERT</code> clause
|
||||
*/
|
||||
private final SQLInsertClause clause;
|
||||
|
||||
/**
|
||||
* @param clause
|
||||
* the insert clause
|
||||
*/
|
||||
public SQLInsertWritableDatabaseRow(SQLInsertClause clause) {
|
||||
this.clause = clause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> WritableDatabaseRow set(Path<T> path, T value) {
|
||||
clause.set(path, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> WritableDatabaseRow setNull(Path<T> path) {
|
||||
return set(path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the insert clause
|
||||
*/
|
||||
public SQLInsertClause getClause() {
|
||||
return clause;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of l2jserver2 <l2jserver2.com>.
|
||||
*
|
||||
* l2jserver2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* l2jserver2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with l2jserver2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jserver.service.database.sql;
|
||||
|
||||
import com.l2jserver.service.database.dao.WritableDatabaseRow;
|
||||
import com.mysema.query.sql.dml.SQLUpdateClause;
|
||||
import com.mysema.query.types.Path;
|
||||
|
||||
/**
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*
|
||||
*/
|
||||
public class SQLUpdateWritableDatabaseRow implements WritableDatabaseRow {
|
||||
/**
|
||||
* The SQL <code>UPDATE</code> clause
|
||||
*/
|
||||
private final SQLUpdateClause clause;
|
||||
|
||||
/**
|
||||
* @param clause
|
||||
* the update clause
|
||||
*/
|
||||
public SQLUpdateWritableDatabaseRow(SQLUpdateClause clause) {
|
||||
this.clause = clause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> WritableDatabaseRow set(Path<T> path, T value) {
|
||||
clause.set(path, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> WritableDatabaseRow setNull(Path<T> path) {
|
||||
return set(path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the update clause
|
||||
*/
|
||||
public SQLUpdateClause getClause() {
|
||||
return clause;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user