From a55a1d55f6197baab3ea0a021c253bcaf0439cce Mon Sep 17 00:00:00 2001 From: Rogiel Date: Sun, 25 Dec 2011 16:30:06 -0200 Subject: [PATCH] Implements insert and update mappers --- .../service/database/dao/AbstractMapper.java | 44 ++++ .../service/database/dao/DatabaseRow.java | 16 +- .../service/database/dao/InsertMapper.java | 51 +++++ .../{Mapper.java => PrimaryKeyMapper.java} | 19 +- .../service/database/dao/SelectMapper.java | 58 ++++++ .../database/dao/SelectPrimaryKeyMapper.java | 63 ++++++ .../service/database/dao/UpdateMapper.java | 40 ++++ .../database/dao/WritableDatabaseRow.java | 46 ++++ .../sql/AbstractSQLDatabaseService.java | 196 ++++++++++++------ .../sql/SQLInsertWritableDatabaseRow.java | 58 ++++++ .../sql/SQLUpdateWritableDatabaseRow.java | 58 ++++++ l2jserver2-gameserver/config/config.xml | 4 +- .../service/database/JDBCDAOModule.java | 14 +- .../{ => dao}/sql/SQLCharacterDAO.java | 142 +++++-------- .../{ => dao}/sql/SQLCharacterFriendDAO.java | 35 ++-- .../sql/SQLCharacterShortcutDAO.java | 44 +--- .../{ => dao}/sql/SQLChatMessageDAO.java | 77 ++----- .../database/{ => dao}/sql/SQLClanDAO.java | 64 +++--- .../database/{ => dao}/sql/SQLItemDAO.java | 123 ++++------- .../database/{ => dao}/sql/SQLNPCDAO.java | 80 ++----- .../mapper/CharacterFriendMapper.java | 58 ++++-- .../database/mapper/CharacterMapper.java | 56 ++++- .../mapper/CharacterShortcutMapper.java | 35 +++- .../database/mapper/ChatMessageMapper.java | 38 +++- .../service/database/mapper/ClanMapper.java | 28 ++- .../service/database/mapper/ItemMapper.java | 43 +++- .../service/database/mapper/NPCMapper.java | 44 +++- .../service/database/model/QCharacter.java | 11 +- .../database/model/QCharacterFriend.java | 15 +- .../database/model/QCharacterShortcut.java | 11 +- .../service/database/model/QClan.java | 11 +- .../service/database/model/QItem.java | 11 +- .../service/database/model/QLogChat.java | 13 +- .../service/database/model/QNPC.java | 15 +- 34 files changed, 1049 insertions(+), 572 deletions(-) create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/AbstractMapper.java create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/InsertMapper.java rename l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/{Mapper.java => PrimaryKeyMapper.java} (74%) create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/SelectMapper.java create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/SelectPrimaryKeyMapper.java create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/UpdateMapper.java create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/WritableDatabaseRow.java create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/SQLInsertWritableDatabaseRow.java create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/SQLUpdateWritableDatabaseRow.java rename l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/{ => dao}/sql/SQLCharacterDAO.java (51%) rename l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/{ => dao}/sql/SQLCharacterFriendDAO.java (84%) rename l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/{ => dao}/sql/SQLCharacterShortcutDAO.java (78%) rename l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/{ => dao}/sql/SQLChatMessageDAO.java (62%) rename l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/{ => dao}/sql/SQLClanDAO.java (73%) rename l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/{ => dao}/sql/SQLItemDAO.java (57%) rename l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/{ => dao}/sql/SQLNPCDAO.java (64%) diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/AbstractMapper.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/AbstractMapper.java new file mode 100644 index 000000000..a30bf99f8 --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/AbstractMapper.java @@ -0,0 +1,44 @@ +/* + * This file is part of l2jserver2 . + * + * 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 . + */ +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 Rogiel + * @param + * the object type + * @param + * the raw id type + * @param + * the id type + * @param + * the table type + * + */ +public abstract class AbstractMapper, E extends RelationalPathBase> + implements SelectMapper, UpdateMapper, + InsertMapper { + @Override + @SuppressWarnings("unchecked") + public SelectMapper getIDMapper(E entity) { + return new SelectPrimaryKeyMapper(getPrimaryKeyMapper(), + (Path) entity.getPrimaryKey().getLocalColumns().get(0)); + } +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/DatabaseRow.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/DatabaseRow.java index 21a6992db..114078821 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/DatabaseRow.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/DatabaseRow.java @@ -24,7 +24,21 @@ import com.mysema.query.types.Path; * @author Rogiel */ public interface DatabaseRow { + /** + * @param + * the path type + * @param path + * the path + * @return the value associated in the row for the given {@link Path} + */ T get(Path path); - + + /** + * @param + * the path type + * @param path + * the path + * @return true if the path has a null value + */ boolean isNull(Path path); } diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/InsertMapper.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/InsertMapper.java new file mode 100644 index 000000000..3ece785d2 --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/InsertMapper.java @@ -0,0 +1,51 @@ +/* + * This file is part of l2jserver2 . + * + * 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 . + */ +package com.l2jserver.service.database.dao; + +import com.l2jserver.model.id.ID; +import com.mysema.query.sql.RelationalPathBase; + +/** + * @author Rogiel + * @param + * the object type + * @param + * the raw id type + * @param + * the id type + * @param + * the table type + */ +public interface InsertMapper, E extends RelationalPathBase> { + /** + * Maps the insert values to the row + * + * @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 getPrimaryKeyMapper(); +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/Mapper.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/PrimaryKeyMapper.java similarity index 74% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/Mapper.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/PrimaryKeyMapper.java index 67cf91f10..c5b4aa6a5 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/Mapper.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/PrimaryKeyMapper.java @@ -16,15 +16,22 @@ */ package com.l2jserver.service.database.dao; -import com.mysema.query.sql.RelationalPathBase; +import com.l2jserver.model.id.ID; /** * @author Rogiel - * @param + * @param * the object type returned by this mapper - * @param - * the entity type + * @param + * the ID raw type */ -public interface Mapper> { - O map(E entity, DatabaseRow row); +public interface PrimaryKeyMapper, R> { + /** + * Reads the ID as an object + * + * @param raw + * the raw id + * @return the {@link ID} object + */ + I createID(R raw); } diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/SelectMapper.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/SelectMapper.java new file mode 100644 index 000000000..6c99345f9 --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/SelectMapper.java @@ -0,0 +1,58 @@ +/* + * This file is part of l2jserver2 . + * + * 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 . + */ +package com.l2jserver.service.database.dao; + +import com.l2jserver.model.id.ID; +import com.mysema.query.sql.RelationalPathBase; + +/** + * @author Rogiel + * @param + * the object type + * @param + * the raw id type + * @param + * the id type + * @param + * the table type + */ +public interface SelectMapper, E extends RelationalPathBase> { + /** + * 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 getIDMapper(E entity); + + /** + * @return the {@link PrimaryKeyMapper} that maps {@link ID}s that will be + * used for caches + */ + PrimaryKeyMapper getPrimaryKeyMapper(); +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/SelectPrimaryKeyMapper.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/SelectPrimaryKeyMapper.java new file mode 100644 index 000000000..e0d70878e --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/SelectPrimaryKeyMapper.java @@ -0,0 +1,63 @@ +/* + * This file is part of l2jserver2 . + * + * 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 . + */ +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 Rogiel + * @param + * the primary key raw type + * @param + * the ID type + * @param + * the table type + */ +public class SelectPrimaryKeyMapper, E extends RelationalPathBase> + implements SelectMapper { + private final PrimaryKeyMapper mapper; + private final Path path; + + /** + * @param mapper + * the {@link PrimaryKeyMapper} + * @param path + * the {@link Path} to the primary key + */ + public SelectPrimaryKeyMapper(PrimaryKeyMapper mapper, Path path) { + this.mapper = mapper; + this.path = path; + } + + @Override + public I select(E entity, DatabaseRow row) { + return mapper.createID(row.get(path)); + } + + @Override + public SelectMapper getIDMapper(E entity) { + return this; + } + + @Override + public PrimaryKeyMapper getPrimaryKeyMapper() { + return mapper; + } + +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/UpdateMapper.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/UpdateMapper.java new file mode 100644 index 000000000..e476b841e --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/UpdateMapper.java @@ -0,0 +1,40 @@ +/* + * This file is part of l2jserver2 . + * + * 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 . + */ +package com.l2jserver.service.database.dao; + +import com.mysema.query.sql.RelationalPathBase; + +/** + * @author Rogiel + * @param + * the object type returned by this mapper + * @param + * the entity type + */ +public interface UpdateMapper> { + /** + * Maps the update values to the row + * + * @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); +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/WritableDatabaseRow.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/WritableDatabaseRow.java new file mode 100644 index 000000000..1f332a95e --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/dao/WritableDatabaseRow.java @@ -0,0 +1,46 @@ +/* + * This file is part of l2jserver2 . + * + * 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 . + */ +package com.l2jserver.service.database.dao; + +import com.mysema.query.types.Path; + +/** + * Database column used to read data + * + * @author Rogiel + */ +public interface WritableDatabaseRow { + /** + * @param + * the path type + * @param path + * the path + * @param value + * the value to be set + * @return this instance + */ + WritableDatabaseRow set(Path path, T value); + + /** + * @param + * the path type + * @param path + * the path to be setted to null + * @return this instance + */ + WritableDatabaseRow setNull(Path path); +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/AbstractSQLDatabaseService.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/AbstractSQLDatabaseService.java index 507d5bc38..d5b1ecb6d 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/AbstractSQLDatabaseService.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/AbstractSQLDatabaseService.java @@ -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. * - *

The {@link Mapper} object

+ *

The {@link SelectMapper} object

* - * 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 Rogiel @@ -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, ?, ?, ?, ?, ?> factory); + R query(SQLQueryFactory, ?, ?, ?, ?, ?> factory, + DatabaseService database); } public static abstract class AbstractQuery implements Query { @@ -674,24 +681,29 @@ public abstract class AbstractSQLDatabaseService extends AbstractService } } - public static abstract class InsertQuery, K> + public static class InsertQuery, E extends RelationalPathBase> extends AbstractQuery { + private final InsertMapper mapper; private final Iterator iterator; - private final Path primaryKey; + private final Path 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 primaryKey, Iterator iterator) { + public InsertQuery(E entity, InsertMapper mapper, + Path primaryKey, Iterator 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 iterator) { - this(entity, null, iterator); + public InsertQuery(E entity, InsertMapper mapper, + Iterator 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 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 primaryKey, O... objects) { - this(entity, primaryKey, Iterators.forArray(objects)); + public InsertQuery(E entity, InsertMapper mapper, + Path primaryKey, O... objects) { + this(entity, mapper, primaryKey, Iterators.forArray(objects)); } @Override + @SuppressWarnings("unchecked") public final Integer query( - SQLQueryFactory, ?, ?, ?, ?, ?> factory) { + SQLQueryFactory, ?, ?, ?, ?, ?> 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) 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> extends AbstractQuery { + private final UpdateMapper mapper; private final Iterator 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 iterator) { + public UpdateQuery(E entity, UpdateMapper mapper, + Iterator 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 mapper, O... objects) { + this(entity, mapper, Iterators.forArray(objects)); } @Override public final Integer query( - SQLQueryFactory, ?, ?, ?, ?, ?> factory) { + SQLQueryFactory, ?, ?, ?, ?, ?> 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> @@ -839,7 +867,8 @@ public abstract class AbstractSQLDatabaseService extends AbstractService @Override public final Integer query( - SQLQueryFactory, ?, ?, ?, ?, ?> factory) { + SQLQueryFactory, ?, ?, ?, ?, ?> 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> + public static abstract class AbstractSelectQuery, E extends RelationalPathBase> extends AbstractQuery { protected final E entity; - protected final Mapper mapper; + protected final SelectMapper mapper; /** * @param entity @@ -868,70 +897,107 @@ public abstract class AbstractSQLDatabaseService extends AbstractService * @param mapper * the object mapper */ - public AbstractSelectQuery(E entity, Mapper mapper) { + public AbstractSelectQuery(E entity, SelectMapper mapper) { this.entity = entity; this.mapper = mapper; } @Override public final R query( - SQLQueryFactory, ?, ?, ?, ?, ?> factory) { + SQLQueryFactory, ?, ?, ?, ?, ?> 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> - extends AbstractSelectQuery { + public static abstract class SelectSingleQuery, E extends RelationalPathBase> + extends AbstractSelectQuery { /** * @param entity * the entity * @param mapper * the mapper */ - public SelectSingleQuery(E entity, Mapper mapper) { + public SelectSingleQuery(E entity, SelectMapper mapper) { super(entity, mapper); } @Override - protected final O perform(AbstractSQLQuery select) { + protected final O perform(AbstractSQLQuery select, + DatabaseService database) { final List 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> - extends AbstractSelectQuery, O, E> { + public static abstract class SelectListQuery, E extends RelationalPathBase> + extends AbstractSelectQuery, O, RI, I, E> { /** * @param entity * the entity * @param mapper * the mapper */ - public SelectListQuery(E entity, Mapper mapper) { + public SelectListQuery(E entity, SelectMapper mapper) { super(entity, mapper); } @Override - protected final List perform(AbstractSQLQuery select) { + protected final List perform(AbstractSQLQuery select, + DatabaseService database) { final List results = select.list(entity.all()); final SQLDatabaseRow row = new SQLDatabaseRow(entity); final List 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); } diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/SQLInsertWritableDatabaseRow.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/SQLInsertWritableDatabaseRow.java new file mode 100644 index 000000000..dae442caa --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/SQLInsertWritableDatabaseRow.java @@ -0,0 +1,58 @@ +/* + * This file is part of l2jserver2 . + * + * 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 . + */ +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 Rogiel + * + */ +public class SQLInsertWritableDatabaseRow implements WritableDatabaseRow { + /** + * The SQL INSERT clause + */ + private final SQLInsertClause clause; + + /** + * @param clause + * the insert clause + */ + public SQLInsertWritableDatabaseRow(SQLInsertClause clause) { + this.clause = clause; + } + + @Override + public WritableDatabaseRow set(Path path, T value) { + clause.set(path, value); + return this; + } + + @Override + public WritableDatabaseRow setNull(Path path) { + return set(path, null); + } + + /** + * @return the insert clause + */ + public SQLInsertClause getClause() { + return clause; + } +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/SQLUpdateWritableDatabaseRow.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/SQLUpdateWritableDatabaseRow.java new file mode 100644 index 000000000..6a30f1bb8 --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/SQLUpdateWritableDatabaseRow.java @@ -0,0 +1,58 @@ +/* + * This file is part of l2jserver2 . + * + * 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 . + */ +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 Rogiel + * + */ +public class SQLUpdateWritableDatabaseRow implements WritableDatabaseRow { + /** + * The SQL UPDATE clause + */ + private final SQLUpdateClause clause; + + /** + * @param clause + * the update clause + */ + public SQLUpdateWritableDatabaseRow(SQLUpdateClause clause) { + this.clause = clause; + } + + @Override + public WritableDatabaseRow set(Path path, T value) { + clause.set(path, value); + return this; + } + + @Override + public WritableDatabaseRow setNull(Path path) { + return set(path, null); + } + + /** + * @return the update clause + */ + public SQLUpdateClause getClause() { + return clause; + } +} diff --git a/l2jserver2-gameserver/config/config.xml b/l2jserver2-gameserver/config/config.xml index f0f856373..a7a29ad17 100644 --- a/l2jserver2-gameserver/config/config.xml +++ b/l2jserver2-gameserver/config/config.xml @@ -21,10 +21,10 @@ - jdbc:derby:data/database/derby;create=true + jdbc:mysql://localhost/l2jserver2 - com.l2jserver.service.database.sql.DerbyDatabaseEngine + com.l2jserver.service.database.sql.MySQLDatabaseEngine