240 lines
9.1 KiB
Java
240 lines
9.1 KiB
Java
package at.ac.tuwien.sepm.assignment.individual.persistence.impl;
|
|
|
|
import at.ac.tuwien.sepm.assignment.individual.entity.Horse;
|
|
import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
|
|
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
|
import at.ac.tuwien.sepm.assignment.individual.exception.PersistenceException;
|
|
import at.ac.tuwien.sepm.assignment.individual.persistence.OwnerDao;
|
|
|
|
import java.lang.invoke.MethodHandles;
|
|
import java.sql.PreparedStatement;
|
|
import java.sql.ResultSet;
|
|
import java.sql.SQLException;
|
|
import java.time.LocalDateTime;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.dao.DataAccessException;
|
|
import org.springframework.dao.DataIntegrityViolationException;
|
|
import org.springframework.dao.EmptyResultDataAccessException;
|
|
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
|
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
|
import org.springframework.jdbc.support.GeneratedKeyHolder;
|
|
import org.springframework.jdbc.support.KeyHolder;
|
|
import org.springframework.stereotype.Repository;
|
|
|
|
@Repository
|
|
public class OwnerJdbcDao implements OwnerDao {
|
|
|
|
private static final String TABLE_NAME = "Owner";
|
|
private static final String HORSE_TABLE_NAME = "Horse";
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
|
private final JdbcTemplate jdbcTemplate;
|
|
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
|
|
|
@Autowired
|
|
public OwnerJdbcDao(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
|
|
this.jdbcTemplate = jdbcTemplate;
|
|
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
|
|
}
|
|
|
|
@Override
|
|
public Owner findOneById(Long id) {
|
|
LOGGER.debug("Get owner with id {}", id);
|
|
final String sql = "SELECT * FROM " + TABLE_NAME + " WHERE id=?";
|
|
List<Owner> owners = jdbcTemplate.query(sql, new Object[] { id }, this::mapRow);
|
|
|
|
if (owners.isEmpty()) throw new NotFoundException("Could not find owner with id " + id);
|
|
|
|
return owners.get(0);
|
|
}
|
|
|
|
@Override
|
|
public List<Owner> getAll() throws NotFoundException {
|
|
LOGGER.debug("Get all owners");
|
|
final String sql = "SELECT * FROM " + TABLE_NAME;
|
|
List<Owner> owners = jdbcTemplate.query(sql, new Object[] { }, this::mapRow);
|
|
|
|
if(owners.isEmpty()) throw new NotFoundException("No owners found in the database");
|
|
|
|
return owners;
|
|
}
|
|
|
|
@Override
|
|
public List<Owner> getFiltered(Map<String, String> filters) throws NotFoundException {
|
|
LOGGER.debug("Get all owners with filters " + filters.entrySet());
|
|
final String sql = "SELECT * FROM " + TABLE_NAME + " WHERE UPPER(name) LIKE :name";
|
|
|
|
// Create a list to hold the results
|
|
List<Owner> owners = new ArrayList<>();
|
|
|
|
// Create a map to hold the sql filters with all values set as wildcards
|
|
Map<String, String> queryFilters = new HashMap<>();
|
|
queryFilters.put("name", "%_%");
|
|
|
|
// Go through the supplied filters and find set values
|
|
if(filters.get("name") != null)
|
|
queryFilters.replace("name", '%' + filters.get("name").toUpperCase() + '%');
|
|
|
|
// Create an map sql parameter source for use in the query
|
|
MapSqlParameterSource sqlMap = new MapSqlParameterSource();
|
|
sqlMap.addValues(queryFilters);
|
|
|
|
owners = namedParameterJdbcTemplate.query(sql, sqlMap, this::mapRow);
|
|
|
|
if(owners.isEmpty()) throw new NotFoundException("No owners found in the database");
|
|
|
|
return owners;
|
|
}
|
|
|
|
@Override
|
|
public List<Horse> getOwnedHorses(Long id) throws NotFoundException {
|
|
LOGGER.debug("Get all horses for owner with id " + id);
|
|
final String sql = "SELECT * FROM " + HORSE_TABLE_NAME + " WHERE owner_id=?";
|
|
|
|
List<Horse> horses = jdbcTemplate.query(sql, new Object[] {id}, BeanPropertyRowMapper.newInstance(Horse.class));
|
|
|
|
if (horses.isEmpty()) throw new NotFoundException("Could not find horses for owner with id " + id);
|
|
|
|
return horses;
|
|
}
|
|
|
|
@Override
|
|
public Owner addOwner(Owner owner) {
|
|
LOGGER.debug("Add owner {}", owner);
|
|
final String sql = "INSERT INTO " + TABLE_NAME + "(name, created_at, updated_at) VALUES(?,?,?)";
|
|
|
|
try {
|
|
// Check if the constraints are violated
|
|
this.validateOwner(owner);
|
|
|
|
LocalDateTime currentTime = LocalDateTime.now();
|
|
|
|
owner.setCreatedAt(currentTime);
|
|
owner.setUpdatedAt(currentTime);
|
|
|
|
// Create a key holder to get the key of the new record
|
|
KeyHolder keyHolder = new GeneratedKeyHolder();
|
|
|
|
int changes = jdbcTemplate.update(connection -> {
|
|
PreparedStatement ps = connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
|
|
|
|
ps.setString(1, owner.getName().trim());
|
|
ps.setObject(2, owner.getCreatedAt());
|
|
ps.setObject(3, owner.getUpdatedAt());
|
|
return ps;
|
|
}, keyHolder);
|
|
|
|
if (changes == 0)
|
|
throw new PersistenceException("Creating owner failed, no rows affected");
|
|
|
|
owner.setId(((Number)keyHolder.getKeys().get("id")).longValue());
|
|
|
|
return owner;
|
|
|
|
} catch (DataAccessException e) {
|
|
throw new PersistenceException("Adding new records failed", e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Owner updateOwner(Owner owner) throws DataAccessException {
|
|
LOGGER.debug("Update owner {}", owner.toString());
|
|
String sql = "UPDATE " + TABLE_NAME + " SET name=?, updated_at=? WHERE id=?";
|
|
|
|
try {
|
|
if(owner.getId() == null || owner.getId() == 0)
|
|
throw new DataIntegrityViolationException("Owner Id missing or 0");
|
|
|
|
this.validateOwner(owner);
|
|
|
|
Owner oldOwner = findOneById(owner.getId());
|
|
|
|
LocalDateTime currentTime = LocalDateTime.now();
|
|
|
|
owner.setUpdatedAt(currentTime);
|
|
|
|
int changes = jdbcTemplate.update(connection -> {
|
|
PreparedStatement ps = connection.prepareStatement(sql);
|
|
|
|
ps.setString(1, owner.getName().trim());
|
|
ps.setObject(2, owner.getUpdatedAt());
|
|
ps.setObject(3, owner.getId());
|
|
return ps;
|
|
});
|
|
|
|
if (changes == 0)
|
|
throw new PersistenceException("Updating owner failed, no rows affected");
|
|
|
|
owner.setCreatedAt(oldOwner.getCreatedAt());
|
|
|
|
return owner;
|
|
} catch(DataAccessException e) {
|
|
throw new PersistenceException("Updating records failed", e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void deleteOwner(Long id) throws DataAccessException, NotFoundException {
|
|
Owner ownerToDelete = this.findOneById(id);
|
|
LOGGER.debug("Delete owner with id {}", id);
|
|
final String sql = "DELETE FROM " + TABLE_NAME + " WHERE id=?";
|
|
|
|
if (ownerOwnsHorses(id))
|
|
throw new DataIntegrityViolationException("Deleting owner failed, owner has horses assigned");
|
|
|
|
try {
|
|
int changes = jdbcTemplate.update(connection -> {
|
|
PreparedStatement ps = connection.prepareStatement(sql);
|
|
ps.setLong(1, id);
|
|
return ps;
|
|
});
|
|
|
|
if (changes == 0)
|
|
throw new PersistenceException("Deleting owner failed, no rows affected");
|
|
|
|
} catch(DataAccessException e){
|
|
throw new PersistenceException("Deleting records failed", e);
|
|
}
|
|
}
|
|
|
|
private void validateOwner(Owner owner) throws DataIntegrityViolationException {
|
|
if(owner.getName() == null || owner.getName().isEmpty())
|
|
throw new DataIntegrityViolationException("Required parameters for owner missing");
|
|
}
|
|
|
|
private boolean ownerOwnsHorses(Long ownerId) {
|
|
final String sql = "SELECT * FROM " + HORSE_TABLE_NAME + " WHERE owner_id=?";
|
|
|
|
try {
|
|
jdbcTemplate.queryForObject(sql, new Object[] {ownerId}, BeanPropertyRowMapper.newInstance(Horse.class));
|
|
} catch(EmptyResultDataAccessException e) {
|
|
// If empty, return false
|
|
return false;
|
|
} catch (IncorrectResultSizeDataAccessException e) {
|
|
// If incorrect size above 0, return true
|
|
return true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private Owner mapRow(ResultSet resultSet, int i) throws SQLException {
|
|
final Owner owner = new Owner();
|
|
owner.setId(resultSet.getLong("id"));
|
|
owner.setName(resultSet.getString("name"));
|
|
owner.setCreatedAt(resultSet.getTimestamp("created_at").toLocalDateTime());
|
|
owner.setUpdatedAt(resultSet.getTimestamp("updated_at").toLocalDateTime());
|
|
return owner;
|
|
}
|
|
|
|
}
|