added docs and annotation validation; fixed pagination

This commit is contained in:
2023-02-10 17:21:47 -05:00
parent 9a43692415
commit 974426c5da
10 changed files with 70 additions and 109 deletions

View File

@@ -7,7 +7,6 @@ import com.poststats.transformer.impl.DaoConverter;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.RequestScoped; import jakarta.enterprise.context.RequestScoped;
@@ -17,9 +16,7 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam; import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response.Status; import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.SecurityContext;
import org.slf4j.Logger; import org.slf4j.Logger;
/** /**
@@ -28,14 +25,11 @@ import org.slf4j.Logger;
@RequestScoped @RequestScoped
@Path("/golf/course/{courseId}") @Path("/golf/course/{courseId}")
@Tag(name = "Course API") @Tag(name = "Course API")
@ApiResponses({ @ApiResponse(responseCode = "200", description = "Success")
@ApiResponse(responseCode = "200", description = "Success"), @ApiResponse(responseCode = "404", description = "A golf course with the specified ID could not be found")
@ApiResponse(responseCode = "401", description = "You are not authorized"),
@ApiResponse(responseCode = "403", description = "You are not identified or authenticated")
})
public class CourseApi { public class CourseApi {
@Parameter(name = "courseId", description = "A unique identifier for a golf course") @Parameter(description = "A unique identifier for a golf course")
@PathParam("courseId") @PathParam("courseId")
private int courseId; private int courseId;
@@ -59,10 +53,7 @@ public class CourseApi {
summary = "Retrieves limited meta-data about a course.", summary = "Retrieves limited meta-data about a course.",
description = "Retreives name, location, and other direct meta-data about the specified course." description = "Retreives name, location, and other direct meta-data about the specified course."
) )
@ApiResponses({ public Course get() {
@ApiResponse(responseCode = "404", description = "A golf course with the specified ID could not be found")
})
public Course get(@Context SecurityContext scontext) {
FlexMap row = this.courseService.get(this.courseId); FlexMap row = this.courseService.get(this.courseId);
if (row == null) if (row == null)
throw new WebApplicationException("Course not found", Status.NOT_FOUND); throw new WebApplicationException("Course not found", Status.NOT_FOUND);

View File

@@ -16,6 +16,11 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.RequestScoped; import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Positive;
import jakarta.ws.rs.BeanParam; import jakarta.ws.rs.BeanParam;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
@@ -25,7 +30,6 @@ import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Response.Status; import jakarta.ws.rs.core.Response.Status;
import java.util.List; import java.util.List;
import org.apache.http.HttpStatus;
import org.slf4j.Logger; import org.slf4j.Logger;
/** /**
@@ -34,6 +38,11 @@ import org.slf4j.Logger;
@RequestScoped @RequestScoped
@Path("/golf/courses") @Path("/golf/courses")
@Tag(name = "Course API") @Tag(name = "Course API")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Success"),
@ApiResponse(responseCode = "400", description = "A query parameter is not valid"),
@ApiResponse(responseCode = "404", description = "No matching golf courses were found")
})
public class CoursesApi { public class CoursesApi {
@Inject @Inject
@@ -57,22 +66,16 @@ public class CoursesApi {
summary = "Searches for golf courses by their name.", summary = "Searches for golf courses by their name.",
description = "Searches for golf courses by their name, excluding prefix (e.g. The) and suffix (e.g. Golf Club), returning limited meta-data about each matched golf course." description = "Searches for golf courses by their name, excluding prefix (e.g. The) and suffix (e.g. Golf Club), returning limited meta-data about each matched golf course."
) )
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Success"),
@ApiResponse(responseCode = "404", description = "No matching golf courses were found"),
@ApiResponse(responseCode = "411", description = "The page number must be at least 1"),
@ApiResponse(responseCode = "413", description = "The page size is too large")
})
@Parameters({ @Parameters({
@Parameter( @Parameter(
name = "name", name = "name",
required = true, required = true,
description = "A fragment or whole golf course name; the prefix and suffix are not included" description = "A fragment or whole golf course name; the prefix and suffix are not included"
), @Parameter(name = "page", description = "A page number, starting at 1", example = "1"), )
@Parameter(name = "perPage", description = "A page size", example = "10")
}) })
@Tag(name = "Search API") @Tag(name = "Search API")
public PagedCollection<List<Course>> searchByName(@QueryParam("name") String name, @BeanParam Pagination paging) { public PagedCollection<List<Course>> searchByName(@QueryParam("name") String name,
@BeanParam @Valid Pagination paging) {
SubList<? extends FlexMap> rows = this.courseService.findByName(name, paging.getPage(), paging.getPerPage()); SubList<? extends FlexMap> rows = this.courseService.findByName(name, paging.getPage(), paging.getPerPage());
if (rows.isEmpty()) if (rows.isEmpty())
throw new WebApplicationException("No matching courses found", Status.NOT_FOUND); throw new WebApplicationException("No matching courses found", Status.NOT_FOUND);
@@ -90,27 +93,19 @@ public class CoursesApi {
summary = "Searches for golf courses by their location.", summary = "Searches for golf courses by their location.",
description = "Searches for golf courses by their major jurisdiction (e.g. US States), returning limited meta-data about each matched golf course." description = "Searches for golf courses by their major jurisdiction (e.g. US States), returning limited meta-data about each matched golf course."
) )
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Success"),
@ApiResponse(
responseCode = "404",
description = "The country, state, or matching golf courses were not found"
), @ApiResponse(responseCode = "411", description = "The page number must be at least 1"),
@ApiResponse(responseCode = "413", description = "The page size is too large")
})
@Parameters({ @Parameters({
@Parameter(name = "country", required = true, description = "A country code", example = "US"), @Parameter(name = "country", required = true, description = "A country code", example = "US"),
@Parameter(name = "state", description = "A State or high-level jurisdiction", example = "FL"), @Parameter(name = "state", description = "A State or high-level jurisdiction", example = "FL")
@Parameter(name = "page", description = "A page number, starting at 1", example = "1"),
@Parameter(name = "perPage", description = "A page size", example = "10")
}) })
@Tag(name = "Search API") @Tag(name = "Search API")
public PagedCollection<List<Course>> searchByJurisdiction(@PathParam("country") String country, public PagedCollection<List<Course>> searchByJurisdiction(@PathParam("country") String country,
@PathParam("state") String state, @BeanParam Pagination paging) { @PathParam("state") String state, @BeanParam @Valid Pagination paging) {
SubList<? extends FlexMap> rows = this.courseService.findByJurisdiction(country, state, paging.getPage(), SubList<? extends FlexMap> rows = this.courseService.findByJurisdiction(country, state, paging.getPage(),
paging.getPerPage()); paging.getPerPage());
if (rows.isEmpty()) if (rows.isEmpty())
throw new WebApplicationException("No matching golf courses found", Status.NOT_FOUND); throw new WebApplicationException("No matching golf courses found", Status.NOT_FOUND);
this.logger.trace("found: {} [{}-{}] of {}", rows.size(), rows.getStartIndex() + 1, rows.getEndIndex(),
rows.getTotal());
return this.converter.convertValue(rows, Course.class).withPage(paging.getPage()) return this.converter.convertValue(rows, Course.class).withPage(paging.getPage())
.withPerPage(paging.getPerPage()); .withPerPage(paging.getPerPage());
@@ -123,15 +118,6 @@ public class CoursesApi {
summary = "Searches for golf courses by their location.", summary = "Searches for golf courses by their location.",
description = "Searches for golf courses by their major jurisdiction (e.g. US States), returning limited meta-data about each matched golf course." description = "Searches for golf courses by their major jurisdiction (e.g. US States), returning limited meta-data about each matched golf course."
) )
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Success"),
@ApiResponse(
responseCode = "400",
description = "A latitude/longitude/radius was outside its natural limits"
), @ApiResponse(responseCode = "404", description = "No golf courses were found"),
@ApiResponse(responseCode = "411", description = "The page number must be at least 1"),
@ApiResponse(responseCode = "413", description = "The page size is too large")
})
@Parameters({ @Parameters({
@Parameter( @Parameter(
name = "latitude", name = "latitude",
@@ -144,30 +130,19 @@ public class CoursesApi {
required = true, required = true,
description = "A longitude in decimal degrees", description = "A longitude in decimal degrees",
example = "-81.34891" example = "-81.34891"
), @Parameter(name = "radius", description = "A search radius in miles", example = "10"), ), @Parameter(name = "radius", description = "A search radius in miles", example = "10")
@Parameter(name = "page", description = "A page number, starting at 1", example = "1"),
@Parameter(name = "perPage", description = "A page size", example = "20")
}) })
@Tag(name = "Search API") @Tag(name = "Search API")
public PagedCollection<List<Course>> searchByJurisdiction(@QueryParam("latitude") double latitude, public PagedCollection<List<Course>> searchByJurisdiction(
@QueryParam("longitude") double longitude, @QueryParam("radius") Integer radiusInMiles, @QueryParam("latitude") @DecimalMin("-90.0") @DecimalMax("90.0") double latitude,
@BeanParam Pagination paging) { @QueryParam("longitude") @DecimalMin("-180.0") @DecimalMax("180.0") double longitude,
if (latitude < -90.0 || latitude > 90.0) @QueryParam("radius") @Positive @Max(100) Integer radiusInMiles, @BeanParam @Valid Pagination paging) {
throw new WebApplicationException("A latitude of -90 to 90 is expected", HttpStatus.SC_BAD_REQUEST);
if (longitude < -180.0 || longitude > 180.0)
throw new WebApplicationException("A longitude of -180 to 180 is expected", HttpStatus.SC_BAD_REQUEST);
if (radiusInMiles == null)
radiusInMiles = 10;
if (radiusInMiles <= 0)
throw new WebApplicationException("A positive radius is expected", HttpStatus.SC_BAD_REQUEST);
if (radiusInMiles > 100)
throw new WebApplicationException("A radius under 100 miles is expected", HttpStatus.SC_BAD_REQUEST);
SubList<? extends FlexMap> rows = this.courseService.findByLocation(latitude, longitude, radiusInMiles, SubList<? extends FlexMap> rows = this.courseService.findByLocation(latitude, longitude, radiusInMiles,
paging.getPage(), paging.getPerPage()); paging.getPage(), paging.getPerPage());
if (rows.isEmpty()) if (rows.isEmpty())
throw new WebApplicationException("No matching facilities found", Status.NOT_FOUND); throw new WebApplicationException("No matching facilities found", Status.NOT_FOUND);
this.logger.trace("found: {} [{}-{}] of {}", rows.size(), rows.getStartIndex() + 1, rows.getEndIndex(),
rows.getTotal());
return this.converter.convertValue(rows, Course.class).withPage(paging.getPage()) return this.converter.convertValue(rows, Course.class).withPage(paging.getPage())
.withPerPage(paging.getPerPage()); .withPerPage(paging.getPerPage());

View File

@@ -2,10 +2,11 @@ package com.poststats.golf.service;
import com.brianlong.util.FlexMap; import com.brianlong.util.FlexMap;
import com.brianlong.util.SubList; import com.brianlong.util.SubList;
import com.poststats.service.CacheableService;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
public interface CourseService { public interface CourseService extends CacheableService<Integer> {
/** /**
* This method retrieves meta-data about the specified course. * This method retrieves meta-data about the specified course.

View File

@@ -1,11 +1,12 @@
package com.poststats.golf.service; package com.poststats.golf.service;
import com.brianlong.util.FlexMap; import com.brianlong.util.FlexMap;
import com.poststats.service.CacheableService;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
public interface EventService { public interface EventService extends CacheableService<Long> {
/** /**
* This method retrieves meta-data about the specified event. * This method retrieves meta-data about the specified event.

View File

@@ -2,10 +2,11 @@ package com.poststats.golf.service;
import com.brianlong.util.FlexMap; import com.brianlong.util.FlexMap;
import com.poststats.golf.security.AuthenticatedPerson; import com.poststats.golf.security.AuthenticatedPerson;
import com.poststats.service.CacheableService;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
public interface PersonService { public interface PersonService extends CacheableService<Long> {
/** /**
* This method builds a `UserPrincipal` object about the golfer. * This method builds a `UserPrincipal` object about the golfer.

View File

@@ -1,10 +1,11 @@
package com.poststats.golf.service; package com.poststats.golf.service;
import com.brianlong.util.FlexMap; import com.brianlong.util.FlexMap;
import com.poststats.service.CacheableService;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
public interface SeriesService { public interface SeriesService extends CacheableService<Integer> {
/** /**
* This method retrieves meta-data about the specified series. * This method retrieves meta-data about the specified series.

View File

@@ -18,10 +18,7 @@ import jakarta.inject.Inject;
import jakarta.inject.Named; import jakarta.inject.Named;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@ApplicationScoped @ApplicationScoped
public class CourseServiceDAO extends CacheableServiceDAO<Integer> implements CourseService { public class CourseServiceDAO extends CacheableServiceDAO<Integer> implements CourseService {
@@ -41,8 +38,8 @@ public class CourseServiceDAO extends CacheableServiceDAO<Integer> implements Co
FlexMap row = super.get(Integer.valueOf(courseId)); FlexMap row = super.get(Integer.valueOf(courseId));
if (row == null) if (row == null)
return null; return null;
row.put("facility", this.facilityService.get(row.getInteger("facilityID")));
this.injectCache(row, this.facilityService, "facilityID", "facility");
return row; return row;
} }
@@ -50,19 +47,14 @@ public class CourseServiceDAO extends CacheableServiceDAO<Integer> implements Co
public Map<Integer, ? extends FlexMap> get(Collection<Integer> courseIds) { public Map<Integer, ? extends FlexMap> get(Collection<Integer> courseIds) {
Map<Integer, ? extends FlexMap> rows = super.get(courseIds); Map<Integer, ? extends FlexMap> rows = super.get(courseIds);
// bulk fetch series from cache/db this.injectCache(rows.values(), this.facilityService, "facilityID", "facility");
Set<Integer> facilityIds = new HashSet<>();
for (Entry<Integer, ? extends FlexMap> row : rows.entrySet())
facilityIds.add(row.getValue().getInteger("facilityId"));
Map<Integer, ? extends FlexMap> facilities = this.facilityService.get(facilityIds);
for (Entry<Integer, ? extends FlexMap> row : rows.entrySet())
row.getValue().put("facility", facilities.get(row.getValue().getInteger("facilityId")));
return rows; return rows;
} }
@Override @Override
public SubList<? extends FlexMap> findByName(String name, int page, int perPage) { public SubList<? extends FlexMap> findByName(String name, int page, int perPage) {
SubList<? extends FlexMap> rows;
try { try {
FlexPreparedStatement fps = this.sqlSelectByName.buildPreparedStatement(); FlexPreparedStatement fps = this.sqlSelectByName.buildPreparedStatement();
try { try {
@@ -70,31 +62,34 @@ public class CourseServiceDAO extends CacheableServiceDAO<Integer> implements Co
fps.setVarchar(2, "%" + name + "%"); fps.setVarchar(2, "%" + name + "%");
fps.setSmallintU(3, (page - 1) * perPage); fps.setSmallintU(3, (page - 1) * perPage);
fps.setSmallintU(4, perPage); fps.setSmallintU(4, perPage);
return (SubList<? extends FlexMap>) fps.executeQuery().getAllRows(); rows = (SubList<? extends FlexMap>) fps.executeQuery().getAllRows();
} finally { } finally {
fps.close(); fps.close();
} }
} catch (SQLException se) { } catch (SQLException se) {
throw new ServiceException(se); throw new ServiceException(se);
} }
this.injectCache(rows, this.facilityService, "facilityID", "facility");
return rows;
} }
@Inject @Inject
@Named(Constants.STATEMENT_PROVIDER_GOLF) @Named(Constants.STATEMENT_PROVIDER_GOLF)
@Statement( @Statement(
feature = ResultSubSetFeature.class, feature = ResultSubSetFeature.class,
sql = "SELECT FP.*, FS.*, F.*, CP.prefix coursePrefix, C.* " sql = "SELECT CP.*, C.* "
+ "FROM ~g~.Course C " + "FROM ~g~.Course C "
+ " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) "
+ " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) "
+ " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) "
+ " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) "
+ "WHERE course LIKE ? OR facility LIKE ? " + "WHERE course LIKE ? OR facility LIKE ? "
) )
private StatementProvider sqlSelectByName; private StatementProvider sqlSelectByName;
@Override @Override
public SubList<? extends FlexMap> findByJurisdiction(String country, String state, int page, int perPage) { public SubList<? extends FlexMap> findByJurisdiction(String country, String state, int page, int perPage) {
SubList<? extends FlexMap> rows;
try { try {
FlexPreparedStatement fps = this.sqlSelectByJurisdiction.buildPreparedStatement(); FlexPreparedStatement fps = this.sqlSelectByJurisdiction.buildPreparedStatement();
try { try {
@@ -102,26 +97,28 @@ public class CourseServiceDAO extends CacheableServiceDAO<Integer> implements Co
fps.setVarchar(2, state); fps.setVarchar(2, state);
fps.setSmallintU(3, (page - 1) * perPage); fps.setSmallintU(3, (page - 1) * perPage);
fps.setSmallintU(4, perPage); fps.setSmallintU(4, perPage);
return (SubList<? extends FlexMap>) fps.executeQuery().getAllRows(); rows = (SubList<? extends FlexMap>) fps.executeQuery().getAllRows();
} finally { } finally {
fps.close(); fps.close();
} }
} catch (SQLException se) { } catch (SQLException se) {
throw new ServiceException(se); throw new ServiceException(se);
} }
this.injectCache(rows, this.facilityService, "facilityID", "facility");
return rows;
} }
@Inject @Inject
@Named(Constants.STATEMENT_PROVIDER_GOLF) @Named(Constants.STATEMENT_PROVIDER_GOLF)
@Statement( @Statement(
feature = ResultSubSetFeature.class, feature = ResultSubSetFeature.class,
sql = "SELECT FP.*, FS.*, F.*, CP.prefix coursePrefix, C.* " sql = "SELECT CP.*, C.* "
+ "FROM ~g~.Course C " + "FROM ~g~.Course C "
+ " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) "
+ " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) "
+ " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " + "WHERE F.addrcountry=? AND F.addrstate=? "
+ " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " + " AND C.deadline IS NULL "
+ "WHERE addrcountry=? AND addrstate=? AND C.deadline IS NULL AND F.deadline IS NULL "
) )
private StatementProvider sqlSelectByJurisdiction; private StatementProvider sqlSelectByJurisdiction;
@@ -129,6 +126,7 @@ public class CourseServiceDAO extends CacheableServiceDAO<Integer> implements Co
public SubList<? extends FlexMap> findByLocation(double latitude, double longitude, int radiusInMiles, int page, public SubList<? extends FlexMap> findByLocation(double latitude, double longitude, int radiusInMiles, int page,
int perPage) { int perPage) {
double degrees = PostStatsSQL.miles2degrees(radiusInMiles); double degrees = PostStatsSQL.miles2degrees(radiusInMiles);
SubList<? extends FlexMap> rows;
try { try {
FlexPreparedStatement fps = this.sqlSelectByGeolocation.buildPreparedStatement(); FlexPreparedStatement fps = this.sqlSelectByGeolocation.buildPreparedStatement();
@@ -139,27 +137,28 @@ public class CourseServiceDAO extends CacheableServiceDAO<Integer> implements Co
fps.setDouble(4, longitude + degrees); fps.setDouble(4, longitude + degrees);
fps.setSmallintU(5, (page - 1) * perPage); fps.setSmallintU(5, (page - 1) * perPage);
fps.setSmallintU(6, perPage); fps.setSmallintU(6, perPage);
return (SubList<? extends FlexMap>) fps.executeQuery().getAllRows(); rows = (SubList<? extends FlexMap>) fps.executeQuery().getAllRows();
} finally { } finally {
fps.close(); fps.close();
} }
} catch (SQLException se) { } catch (SQLException se) {
throw new ServiceException(se); throw new ServiceException(se);
} }
this.injectCache(rows, this.facilityService, "facilityID", "facility");
return rows;
} }
@Inject @Inject
@Named(Constants.STATEMENT_PROVIDER_GOLF) @Named(Constants.STATEMENT_PROVIDER_GOLF)
@Statement( @Statement(
feature = ResultSubSetFeature.class, feature = ResultSubSetFeature.class,
sql = "SELECT FP.*, FS.*, F.*, CP.prefix coursePrefix, C.* " sql = "SELECT CP.*, C.* "
+ "FROM ~g~.Course C " + "FROM ~g~.Course C "
+ " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) "
+ " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) "
+ " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) "
+ " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) "
+ "WHERE F.latitude>=? AND F.latitude<=? AND F.longitude>=? AND F.longitude<=? " + "WHERE F.latitude>=? AND F.latitude<=? AND F.longitude>=? AND F.longitude<=? "
+ " AND C.deadline IS NULL AND F.deadline IS NULL " + " AND C.deadline IS NULL "
) )
private StatementProvider sqlSelectByGeolocation; private StatementProvider sqlSelectByGeolocation;

View File

@@ -35,8 +35,9 @@ public class EventRoundServiceDAO extends CacheableServiceDAO<Long> implements E
FlexMap row = super.get(Long.valueOf(eventId)); FlexMap row = super.get(Long.valueOf(eventId));
if (row == null) if (row == null)
return null; return null;
row.put("course", this.courseService.get(row.getInteger("courseID")));
this.injectCache(row, this.courseService, "courseID", "course");
row.put("course", this.courseService.get(row.getInteger("courseID")));
return row; return row;
} }

View File

@@ -17,7 +17,6 @@ import java.sql.SQLException;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ApplicationScoped @ApplicationScoped
@@ -38,8 +37,8 @@ public class EventServiceDAO extends CacheableServiceDAO<Long> implements EventS
FlexMap row = super.get(Long.valueOf(eventId)); FlexMap row = super.get(Long.valueOf(eventId));
if (row == null) if (row == null)
return null; return null;
row.put("series", this.seriesService.get(row.getInteger("seriesID")));
this.injectCache(row, this.seriesService, "seriesID", "series");
return row; return row;
} }
@@ -47,14 +46,7 @@ public class EventServiceDAO extends CacheableServiceDAO<Long> implements EventS
public Map<Long, ? extends FlexMap> get(Collection<Long> eventIds) { public Map<Long, ? extends FlexMap> get(Collection<Long> eventIds) {
Map<Long, ? extends FlexMap> rows = super.get(eventIds); Map<Long, ? extends FlexMap> rows = super.get(eventIds);
// bulk fetch series from cache/db this.injectCache(rows.values(), this.seriesService, "seriesID", "series");
Set<Integer> seriesIds = new HashSet<>();
for (Entry<Long, ? extends FlexMap> row : rows.entrySet())
seriesIds.add(row.getValue().getInteger("seriesId"));
Map<Integer, ? extends FlexMap> serieses = this.seriesService.get(seriesIds);
for (Entry<Long, ? extends FlexMap> row : rows.entrySet())
row.getValue().put("series", serieses.get(row.getValue().getInteger("seriesID")));
return rows; return rows;
} }

View File

@@ -25,7 +25,6 @@ import java.sql.SQLException;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ApplicationScoped @ApplicationScoped
@@ -74,16 +73,16 @@ public class PersonServiceDAO extends CacheableServiceDAO<Long> implements Perso
FlexMap row = this.get(Long.valueOf(personId)); FlexMap row = this.get(Long.valueOf(personId));
if (row == null) if (row == null)
return null; return null;
row.put("person", this.poststatsPersonService.get(personId));
this.injectCache(row, this.poststatsPersonService, "personID", "person");
return row; return row;
} }
@Override @Override
public Map<Long, ? extends FlexMap> get(Collection<Long> ids) { public Map<Long, ? extends FlexMap> get(Collection<Long> ids) {
Map<Long, ? extends FlexMap> rows = super.get(ids); Map<Long, ? extends FlexMap> rows = super.get(ids);
Map<Long, ? extends FlexMap> persons = this.poststatsPersonService.get(ids);
for (Entry<Long, ? extends FlexMap> row : rows.entrySet()) this.injectCache(rows.values(), this.poststatsPersonService, "personID", "person");
row.getValue().put("person", persons.get(row.getKey()));
return rows; return rows;
} }