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

com.wandrell.persistence.repository.SpringJDBCRepository Maven / Gradle / Ivy

There is a newer version: 0.1.9
Show newest version
/**
 * The MIT License (MIT)
 * 

* Copyright (c) 2015 the original author or authors. *

* Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: *

* The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. *

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.wandrell.persistence.repository; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Collection; import javax.sql.DataSource; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import com.wandrell.pattern.repository.DefaultQueryData; import com.wandrell.pattern.repository.FilteredRepository; import com.wandrell.pattern.repository.QueryData; import com.wandrell.persistence.PersistenceEntity; /** * Implementation of {@code FilteredRepository} prepared to work with Spring's * JDBC API. *

* For this reason, it makes use of SQL queries, to which a simple JPA * templating mechanism will be applied. *

* For example, a query could be like this: *

* {@code SELECT name FROM employees WHERE id = :id} *

* Meaning that the query expects a parameter {@code id}, which will take the * place of the {@code :id} placeholder. *

* Both the query and the parameters will be received on a {@code QueryData} * object, which comes from the * Java Patterns * library. *

* A few initial queries are required. These are for updating and deleting * entities. These should be created by the user, following a simple pattern. *

* The delete query is simple, it will just require knowing the ID of the * entity, so it can be something like this: *

* {@code DELETE FROM employees WHERE id = :id"} *

* The update query requires all the columns which will be updated, and could be * something like this: *

* {@code UPDATE employees SET name = :name WHERE id = :id} *

* As note to take into consideration, when using the * {@link #add(PersistenceEntity) add} and the {@link #update(PersistenceEntity) * update} methods both will work the same. If the received entity lacks a code * it will be added into the database, otherwise the stored entity will be * updated. * * @author Bernardo Martínez Garrido * @param * the type stored on the repository * @see QueryData * @see PersistenceEntity */ public final class SpringJDBCRepository implements FilteredRepository { /** * The class of the objects to be returned. */ private final Class classType; /** * Query for deleting entities. */ private final String deleteQuery; /** * Query for acquiring all the entities. */ private final QueryData getAllQuery; /** * Query for inserting entities. */ private final SimpleJdbcInsert insert; /** * Template for running the queries. */ private final NamedParameterJdbcTemplate jdbcTemplate; /** * Query for updating entities. */ private final String updateQuery; /** * Constructs a {@code JPARepository} with the specified data and queries. *

* It will require a templated query both for updating and deleting an * entity. *

* An additional query, used for acquiring all the entities, will be built * from the received table. And the keys, representing the table's primary * keys, will be used to prepare the insert query for new entities. * * @param type * the class of the objects to be returned * @param dataSource * JPA source of the data * @param update * query for updating an entity on the database * @param delete * query for deleting an entity on the database * @param table * table where the repository will execute the queries * @param keys * primary keys of the table */ public SpringJDBCRepository(final Class type, final DataSource dataSource, final String update, final String delete, final String table, final String... keys) { super(); checkNotNull(type, "Received a null pointer as the class type"); checkNotNull(dataSource, "Received a null pointer as the data source"); checkNotNull(update, "Received a null pointer as the update query"); checkNotNull(delete, "Received a null pointer as the delete query"); checkNotNull(table, "Received a null pointer as the table"); checkNotNull(keys, "Received a null pointer as the key columns"); this.classType = type; // Queries getAllQuery = new DefaultQueryData( String.format("SELECT * FROM %s", table)); this.updateQuery = update; this.deleteQuery = delete; insert = new SimpleJdbcInsert(dataSource).withTableName(table) .usingGeneratedKeyColumns(keys); jdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } /** * Adds an entity to the repository. *

* Note that both the {@code add} and the {@link #update(PersistenceEntity) * update} methods work the same, as if the entity does not exist it will be * added, but if it already exists then it will be updated. * * @param entity * the entity to add */ @Override public final void add(final V entity) { final BeanPropertySqlParameterSource parameterSource; // Bean-based // parameters // source final Number newKey; // Key assigned to the new entity checkNotNull(entity, "Received a null pointer as the entity"); parameterSource = new BeanPropertySqlParameterSource(entity); if ((entity.getId() == null) || (entity.getId() < 0)) { newKey = getInsert().executeAndReturnKey(parameterSource); entity.setId(newKey.intValue()); } else { getTemplate().update(getUpdateQuery(), parameterSource); } } /** * Returns all the entities contained in the repository. * * @return all the entities contained in the repository */ @Override public final Collection getAll() { return getCollection(getAllValuesQuery()); } /** * Queries the entities in the repository and returns a subset of them. *

* The collection is created by building a query from the received * {@code QueryData} and executing it. * * @param query * the query user to acquire the entities * @return the queried subset of entities */ @Override public final Collection getCollection(final QueryData query) { checkNotNull(query, "Received a null pointer as the query"); return getTemplate().query(query.getQuery(), query.getParameters(), BeanPropertyRowMapper.newInstance(getType())); } /** * Queries the entities in the repository and returns a single one. *

* The entity is acquired by building a query from the received * {@code QueryData} and executing it. * * @param query * the query user to acquire the entities * @return the queried entity */ @Override public final V getEntity(final QueryData query) { V entity; // Entity acquired from the query checkNotNull(query, "Received a null pointer as the query"); // Tries to acquire the entity try { entity = getTemplate().queryForObject(query.getQuery(), query.getParameters(), BeanPropertyRowMapper.newInstance(getType())); } catch (final EmptyResultDataAccessException exception) { entity = null; } return entity; } /** * Removes an entity from the repository. * * @param entity * the entity to remove */ @Override public final void remove(final V entity) { final BeanPropertySqlParameterSource parameterSource; // Bean-based // parameters // source parameterSource = new BeanPropertySqlParameterSource(entity); getTemplate().update(getDeleteQuery(), parameterSource); } /** * Adds an entity to the repository. *

* Note that both the {@link #add(PersistenceEntity) add} and the * {@code update} methods work the same, as if the entity does not exist it * will be added, but if it already exists then it will be updated. * * @param entity * the entity to add */ @Override public final void update(final V entity) { add(entity); } /** * Returns the query used to retrieving all the entities. * * @return the query for retrieving all the entities */ private final QueryData getAllValuesQuery() { return getAllQuery; } /** * Returns the query used for deleting an entity. * * @return the query for deleting an entity */ private final String getDeleteQuery() { return deleteQuery; } /** * Returns the query used for inserting an entity. * * @return the query for inserting an entity */ private final SimpleJdbcInsert getInsert() { return insert; } /** * Returns the template used for executing the queries. * * @return the template for executing the queries */ private final NamedParameterJdbcTemplate getTemplate() { return jdbcTemplate; } /** * Returns the class of the objects returned by the repository. * * @return the class of the objects returned by the repository */ private final Class getType() { return classType; } /** * Returns the query used for updating an entity. * * @return the query for updating an entity */ private final String getUpdateQuery() { return updateQuery; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy