feat: add fetch size, max-rows, timeout settings

This commit is contained in:
Sergey Krylov 2026-03-05 05:29:10 +03:00
parent 168e9a99c7
commit e868169f3d
13 changed files with 457 additions and 107 deletions

View File

@ -2,3 +2,6 @@ app.datasource.url=jdbc:postgresql://localhost:5434/charm_repository
app.datasource.username=postgres app.datasource.username=postgres
app.datasource.password=123456 app.datasource.password=123456
app.datasource.driver=org.postgresql.Driver app.datasource.driver=org.postgresql.Driver
app.datasource.fetch-size=50
app.datasource.max-rows=100
app.datasource.query-timeout=5

View File

@ -10,8 +10,10 @@ import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import ru.charm.back.dto.ProfileFilter;
import ru.charm.back.dto.ProfileGetDto; import ru.charm.back.dto.ProfileGetDto;
import ru.charm.back.dto.ProfileUpdateDto; import ru.charm.back.dto.ProfileUpdateDto;
import ru.charm.back.mapper.RequestToProfileFilterMapper;
import ru.charm.back.mapper.RequestToProfileUpdateDtoMapper; import ru.charm.back.mapper.RequestToProfileUpdateDtoMapper;
import ru.charm.back.service.ProfileService; import ru.charm.back.service.ProfileService;
@ -27,6 +29,8 @@ public class ProfileController extends HttpServlet {
private final ProfileService service = ProfileService.getInstance(); private final ProfileService service = ProfileService.getInstance();
private final RequestToProfileUpdateDtoMapper requestToProfileUpdateDtoMapper = RequestToProfileUpdateDtoMapper.getInstance(); private final RequestToProfileUpdateDtoMapper requestToProfileUpdateDtoMapper = RequestToProfileUpdateDtoMapper.getInstance();
private final RequestToProfileFilterMapper requestToProfileFilterMapper = RequestToProfileFilterMapper.getInstance();
@Override @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
@ -66,7 +70,8 @@ public class ProfileController extends HttpServlet {
resp.sendError(SC_NOT_FOUND); resp.sendError(SC_NOT_FOUND);
} }
} else { } else {
req.setAttribute("profiles", service.findAll()); ProfileFilter filter = requestToProfileFilterMapper.map(req);
req.setAttribute("profiles", service.findAll(filter));
req.getRequestDispatcher("/WEB-INF/jsp/profiles.jsp").forward(req, resp); req.getRequestDispatcher("/WEB-INF/jsp/profiles.jsp").forward(req, resp);
} }
} }

View File

@ -9,7 +9,9 @@ import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import ru.charm.back.dto.ProfileFilter;
import ru.charm.back.dto.ProfileGetDto; import ru.charm.back.dto.ProfileGetDto;
import ru.charm.back.mapper.RequestToProfileFilterMapper;
import ru.charm.back.service.ProfileService; import ru.charm.back.service.ProfileService;
import java.io.IOException; import java.io.IOException;
@ -23,6 +25,8 @@ import static ru.charm.back.utils.UrlUtils.REST_URL;
@MultipartConfig @MultipartConfig
public class ProfileController extends HttpServlet { public class ProfileController extends HttpServlet {
private final ProfileService service = ProfileService.getInstance(); private final ProfileService service = ProfileService.getInstance();
private final RequestToProfileFilterMapper requestToProfileFilterMapper = RequestToProfileFilterMapper.getInstance();
private final ObjectMapper objectMapper = JsonMapper.builder() private final ObjectMapper objectMapper = JsonMapper.builder()
.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true) .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
@ -45,7 +49,8 @@ public class ProfileController extends HttpServlet {
resp.sendError(SC_NOT_FOUND); resp.sendError(SC_NOT_FOUND);
} }
} else { } else {
objectMapper.writeValue(writer, service.findAll()); ProfileFilter filter = requestToProfileFilterMapper.map(req);
objectMapper.writeValue(writer, service.findAll(filter));
} }
} }
} }

View File

@ -4,38 +4,39 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import ru.charm.back.dto.ProfileFilter;
import ru.charm.back.dto.ProfileSelectQueryBuilder;
import ru.charm.back.dto.ProfileUpdateQueryBuilder;
import ru.charm.back.dto.Query;
import ru.charm.back.model.Gender; import ru.charm.back.model.Gender;
import ru.charm.back.model.Profile; import ru.charm.back.model.Profile;
import ru.charm.back.model.Role; import ru.charm.back.model.Role;
import ru.charm.back.model.Status; import ru.charm.back.model.Status;
import ru.charm.back.utils.ConfigFile; import ru.charm.back.utils.ConfigFileUtils;
import ru.charm.back.utils.ConnectionManager;
import java.sql.*; import java.sql.*;
import java.sql.Date; import java.sql.Date;
import java.util.*; import java.util.*;
import static ru.charm.back.utils.ConnectionManager.getConnection;
@Slf4j @Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ProfileDao { public class ProfileDao {
public static final String INSERT = "INSERT INTO profile (email, password) VALUES (?, ?)";
private static final ProfileDao INSTANCE = new ProfileDao(); private static final ProfileDao INSTANCE = new ProfileDao();
public static final String URL = ConfigFile.get("app.datasource.url");
public static final String USER = ConfigFile.get("app.datasource.username");
public static final String PASSWORD = ConfigFile.get("app.datasource.password");
public static final String DRIVER = ConfigFile.get("app.datasource.driver");
@SneakyThrows @SneakyThrows
public static ProfileDao getInstance() { public static ProfileDao getInstance() {
Class.forName(DRIVER);
return INSTANCE; return INSTANCE;
} }
public Profile save(Profile profile) { public Profile save(Profile profile) {
String sql = "INSERT INTO profile(email, password) VALUES (?, ?)";
try ( try (
Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); PreparedStatement statement = connection.prepareStatement(INSERT, Statement.RETURN_GENERATED_KEYS);
) { ) {
statement.setString(1, profile.getEmail()); statement.setString(1, profile.getEmail());
@ -54,13 +55,15 @@ public class ProfileDao {
} }
} }
public Optional<Profile> findById(Long id) { public Optional<Profile> findById(Long id) {
Query query = new ProfileSelectQueryBuilder().addIdFilter(id).build();
try ( try (
Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Connection connection = getConnection();
Statement statement = connection.createStatement(); PreparedStatement statement = ConnectionManager.getPreparedStmt(connection, query);
) { ) {
String sql = "SELECT * FROM profile WHERE id = '%s'".formatted(id); ResultSet res = statement.executeQuery();
ResultSet res = statement.executeQuery(sql);
Profile profile = null; Profile profile = null;
if (res.next()) { if (res.next()) {
@ -74,13 +77,24 @@ public class ProfileDao {
} }
} }
public List<Profile> findAll() { public List<Profile> findAll(ProfileFilter filter) {
Query query = new ProfileSelectQueryBuilder()
.addEmailStartWithFilter(filter.getEmailStartWith())
.addNameStartWith(filter.getNameStartWith())
.addSurnameStartWith(filter.getSurnameStartWith())
.addStatus(filter.getStatus())
.addLTAge(filter.getLtAge())
.addGTEAge(filter.getGteAge())
.build();
try ( try (
Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Connection connection = ConnectionManager.getConnection();
Statement statement = connection.createStatement(); PreparedStatement statement = ConnectionManager.getPreparedStmt(connection, query);
) { ) {
String sql = "SELECT * FROM profile" ; statement.setFetchSize(ConnectionManager.FETCH_SIZE);
ResultSet res = statement.executeQuery(sql); statement.setMaxRows(ConnectionManager.MAX_ROWS);
statement.setQueryTimeout(ConnectionManager.QUERY_TIMEOUT);
ResultSet res = statement.executeQuery();
List<Profile> profiles = new ArrayList<>(); List<Profile> profiles = new ArrayList<>();
while (res.next()) { while (res.next()) {
@ -94,81 +108,32 @@ public class ProfileDao {
} }
} }
public Optional<Profile> findByEmailAndPassword(String email, String password) {
try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
Statement stmt = conn.createStatement()) {
//language=POSTGRES-PSQL
String sql = "SELECT * FROM profile WHERE email = '%s' AND password = '%s'";
ResultSet rs = stmt.executeQuery(String.format(sql, email, password));
Profile profile = null;
if (rs.next()) {
profile = mapToProfile(rs);
}
return Optional.ofNullable(profile);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void update(Profile profile) { public void update(Profile profile) {
try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD); Query query = new ProfileUpdateQueryBuilder()
Statement stmt = conn.createStatement()) { .addEmail(profile.getEmail())
List<Object> args = new ArrayList<>(); .addPassword(profile.getPassword())
StringBuilder queryBuilder = new StringBuilder("UPDATE profile SET email = '%s', password = '%s'"); .addName(profile.getName())
args.add(profile.getEmail()); .addSurname(profile.getSurname())
args.add(profile.getPassword()); .addBirthDate(profile.getBirthDate())
.addAbout(profile.getAbout())
.addGender(profile.getGender())
.addStatus(profile.getStatus())
.addPhoto(profile.getPhoto())
.build(profile.getId());
if (profile.getName() != null) { try (Connection conn = ConnectionManager.getConnection();
queryBuilder.append(", name = '%s'"); PreparedStatement stmt = ConnectionManager.getPreparedStmt(conn, query)) {
args.add(profile.getName()); stmt.executeUpdate();
}
if (profile.getSurname() != null) {
queryBuilder.append(", surname = '%s'");
args.add(profile.getSurname());
}
if (profile.getBirthDate() != null) {
queryBuilder.append(", birth_date = '%s'");
args.add(Date.valueOf(profile.getBirthDate()));
}
if (profile.getAbout() != null) {
queryBuilder.append(", about = '%s'");
args.add(profile.getAbout());
}
if (profile.getGender() != null) {
queryBuilder.append(", gender = '%s'");
args.add(profile.getGender());
}
if (profile.getStatus() != null) {
queryBuilder.append(", status = '%s'");
args.add(profile.getStatus());
}
if (profile.getPhoto() != null) {
queryBuilder.append(", photo = '%s'");
args.add(profile.getPhoto());
}
queryBuilder.append(" WHERE id = %s");
args.add(profile.getId());
String sql = queryBuilder.toString().formatted(args.toArray());
log.debug("Final update sql: {}", sql);
int updateCount = stmt.executeUpdate(sql);
log.debug("Update count: {}", updateCount);
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public boolean delete(Long id) { public boolean delete(Long id) {
try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD); String sql = "DELETE FROM profile WHERE id = ?";
Statement stmt = conn.createStatement()) { try (Connection conn = getConnection();
//language=POSTGRES-PSQL PreparedStatement stmt = conn.prepareStatement(sql)) {
String sql = "DELETE FROM profile WHERE id = %s".formatted(id); int deleteCount = stmt.executeUpdate();
int deleteCount = stmt.executeUpdate(sql);
log.debug("Delete count: {}", deleteCount); log.debug("Delete count: {}", deleteCount);
return deleteCount > 0; return deleteCount > 0;
} catch (SQLException e) { } catch (SQLException e) {
@ -178,7 +143,7 @@ public class ProfileDao {
public Set<String> getAllEmails() { public Set<String> getAllEmails() {
try ( try (
Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Connection connection = getConnection();
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
) { ) {
String sql = "SELECT email FROM profile" ; String sql = "SELECT email FROM profile" ;
@ -197,11 +162,11 @@ public class ProfileDao {
} }
public Optional<Profile> findByEmail(String email) { public Optional<Profile> findByEmail(String email) {
String sql = "SELECT * FROM profile WHERE email = ?"; Query query = new ProfileSelectQueryBuilder().addEmailFilter(email).build();
try ( try (
Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Connection connection = ConnectionManager.getConnection();
PreparedStatement statement = connection.prepareStatement(sql); PreparedStatement statement = ConnectionManager.getPreparedStmt(connection, query);
) { ) {
statement.setString(1, email); statement.setString(1, email);
ResultSet res = statement.executeQuery(); ResultSet res = statement.executeQuery();
@ -219,12 +184,13 @@ public class ProfileDao {
} }
public Boolean existsByEmail(String email) { public Boolean existsByEmail(String email) {
Query query = new ProfileSelectQueryBuilder().addEmailFilter(email).build();
try ( try (
Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Connection connection = ConnectionManager.getConnection();
Statement statement = connection.createStatement(); PreparedStatement statement = ConnectionManager.getPreparedStmt(connection, query);
) { ) {
String sql = "SELECT * FROM profile WHERE email = '%s'".formatted(email); ResultSet res = statement.executeQuery();
ResultSet res = statement.executeQuery(sql);
return res.next(); return res.next();

View File

@ -0,0 +1,17 @@
package ru.charm.back.dto;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import ru.charm.back.model.Status;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ProfileFilter {
String emailStartWith;
String nameStartWith;
String surnameStartWith;
Integer ltAge;
Integer gteAge;
Status status;
}

View File

@ -0,0 +1,115 @@
package ru.charm.back.dto;
import ru.charm.back.model.Status;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import static ru.charm.back.utils.DateTimeUtils.getPastDate;
public class ProfileSelectQueryBuilder {
//language=POSTGRES-PSQL
public static final String SELECT_BASE = """
SELECT id, email, password, "name", surname, birth_date, about, gender, photo, status, role
FROM profile
WHERE '' = ''
""";
private final StringBuilder sb;
private final List<Object> args;
public ProfileSelectQueryBuilder() {
this.sb = new StringBuilder(SELECT_BASE);
this.args = new ArrayList<>();
}
public ProfileSelectQueryBuilder addIdFilter(Long id) {
if (id == null) {
return this;
}
sb.append(" AND id = ?");
args.add(id);
return this;
}
public ProfileSelectQueryBuilder addEmailFilter(String email) {
if (email == null) {
return this;
}
sb.append(" AND email = ?");
args.add(email);
return this;
}
public ProfileSelectQueryBuilder addPasswordFilter(String password) {
if (password == null) {
return this;
}
sb.append(" AND password = ?");
args.add(password);
return this;
}
public ProfileSelectQueryBuilder addEmailStartWithFilter(String emailStartWith) {
if (emailStartWith == null) {
return this;
}
sb.append(" AND email like ?");
args.add(emailStartWith + "%");
return this;
}
public ProfileSelectQueryBuilder addNameStartWith(String nameStartWith) {
if (nameStartWith == null) {
return this;
}
sb.append(" AND name like ?");
args.add(nameStartWith + "%");
return this;
}
public ProfileSelectQueryBuilder addSurnameStartWith(String surnameStartWith) {
if (surnameStartWith == null) {
return this;
}
sb.append(" AND surname like ?");
args.add(surnameStartWith + "%");
return this;
}
public ProfileSelectQueryBuilder addLTAge(Integer ltAge) {
if (ltAge == null) {
return this;
}
Date gtDate = getPastDate(ltAge);
sb.append(" AND birth_date > ?");
args.add(gtDate);
return this;
}
public ProfileSelectQueryBuilder addGTEAge(Integer gteAge) {
if (gteAge == null) {
return this;
}
Date lteDate = getPastDate(gteAge);
sb.append(" AND birth_date <= ?");
args.add(lteDate);
return this;
}
public ProfileSelectQueryBuilder addStatus(Status status) {
if (status == null) {
return this;
}
sb.append(" AND status = ?");
args.add(status.toString());
return this;
}
public Query build() {
return new Query(sb.toString(), args);
}
}

View File

@ -0,0 +1,109 @@
package ru.charm.back.dto;
import ru.charm.back.model.Gender;
import ru.charm.back.model.Status;
import java.sql.Date;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class ProfileUpdateQueryBuilder {
//language=POSTGRES-PSQL
public static final String UPDATE_BASE = "UPDATE profile SET id = id";
private final StringBuilder sb;
private final List<Object> args;
public ProfileUpdateQueryBuilder() {
this.sb = new StringBuilder(UPDATE_BASE);
this.args = new ArrayList<>();
}
public ProfileUpdateQueryBuilder addEmail(String email) {
if (email == null) {
return this;
}
sb.append(", email = ?");
args.add(email);
return this;
}
public ProfileUpdateQueryBuilder addPassword(String password) {
if (password == null) {
return this;
}
sb.append(", password = ?");
args.add(password);
return this;
}
public ProfileUpdateQueryBuilder addName(String name) {
if (name == null) {
return this;
}
sb.append(", name = ?");
args.add(name);
return this;
}
public ProfileUpdateQueryBuilder addSurname(String surname) {
if (surname == null) {
return this;
}
sb.append(", surname = ?");
args.add(surname);
return this;
}
public ProfileUpdateQueryBuilder addBirthDate(LocalDate birthDate) {
if (birthDate == null) {
return this;
}
sb.append(", birth_date = ?");
args.add(Date.valueOf(birthDate));
return this;
}
public ProfileUpdateQueryBuilder addAbout(String about) {
if (about == null) {
return this;
}
sb.append(", about = ?");
args.add(about);
return this;
}
public ProfileUpdateQueryBuilder addGender(Gender gender) {
if (gender == null) {
return this;
}
sb.append(", gender = ?");
args.add(gender.toString());
return this;
}
public ProfileUpdateQueryBuilder addStatus(Status status) {
if (status == null) {
return this;
}
sb.append(", status = ?");
args.add(status.toString());
return this;
}
public ProfileUpdateQueryBuilder addPhoto(String photo) {
if (photo == null) {
return this;
}
sb.append(", photo = ?");
args.add(photo);
return this;
}
public Query build(Long id) {
sb.append(" WHERE id = ?");
args.add(id);
return new Query(sb.toString(), args);
}
}

View File

@ -0,0 +1,6 @@
package ru.charm.back.dto;
import java.util.List;
public record Query(String sql, List<Object> args) {
}

View File

@ -0,0 +1,54 @@
package ru.charm.back.mapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import ru.charm.back.dto.ProfileFilter;
import ru.charm.back.model.Status;
import static ru.charm.back.utils.StringUtils.isBlank;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RequestToProfileFilterMapper implements Mapper<HttpServletRequest, ProfileFilter> {
private static final RequestToProfileFilterMapper INSTANCE = new RequestToProfileFilterMapper();
public static RequestToProfileFilterMapper getInstance() {
return INSTANCE;
}
@Override
public ProfileFilter map(HttpServletRequest req) {
return map(req, new ProfileFilter());
}
@Override
public ProfileFilter map(HttpServletRequest req, ProfileFilter filter) {
String emailStartWithArg = req.getParameter("emailStartWith");
String emailStartWith = isBlank(emailStartWithArg) ? null : emailStartWithArg;
filter.setEmailStartWith(emailStartWith);
String nameStartWithArg = req.getParameter("nameStartWith");
String nameStartWith = isBlank(nameStartWithArg) ? null : nameStartWithArg;
filter.setNameStartWith(nameStartWith);
String surnameStartWithArg = req.getParameter("surnameStartWith");
String surnameStartWith = isBlank(surnameStartWithArg) ? null : surnameStartWithArg;
filter.setSurnameStartWith(surnameStartWith);
String ltAgeArg = req.getParameter("ltAge");
Integer ltAge = isBlank(ltAgeArg) ? null : Integer.parseInt(ltAgeArg);
filter.setLtAge(ltAge);
String gteAgeArg = req.getParameter("gteAge");
Integer gteAge = isBlank(gteAgeArg) ? null : Integer.parseInt(gteAgeArg);
filter.setGteAge(gteAge);
String statusArg = req.getParameter("status");
Status status = isBlank(statusArg) ? null : Status.valueOf(statusArg);
filter.setStatus(status);
return filter;
}
}

View File

@ -4,10 +4,7 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import ru.charm.back.dao.ProfileDao; import ru.charm.back.dao.ProfileDao;
import ru.charm.back.dto.LoginDto; import ru.charm.back.dto.*;
import ru.charm.back.dto.ProfileGetDto;
import ru.charm.back.dto.ProfileUpdateDto;
import ru.charm.back.dto.RegistrationDto;
import ru.charm.back.mapper.ProfileToProfileGetDtoMapper; import ru.charm.back.mapper.ProfileToProfileGetDtoMapper;
import ru.charm.back.mapper.ProfileUpdateDtoToProfileMapper; import ru.charm.back.mapper.ProfileUpdateDtoToProfileMapper;
import ru.charm.back.mapper.RegistrationDtoToProfileMapper; import ru.charm.back.mapper.RegistrationDtoToProfileMapper;
@ -46,8 +43,8 @@ public class ProfileService {
return dao.findById(id).map(profileToProfileGetDtoMapper::map); return dao.findById(id).map(profileToProfileGetDtoMapper::map);
} }
public List<ProfileGetDto> findAll() { public List<ProfileGetDto> findAll(ProfileFilter filter) {
return dao.findAll().stream().map(profileToProfileGetDtoMapper::map).toList(); return dao.findAll(filter).stream().map(profileToProfileGetDtoMapper::map).toList();
} }
@SneakyThrows @SneakyThrows

View File

@ -7,7 +7,7 @@ import java.io.InputStream;
import java.util.Properties; import java.util.Properties;
@UtilityClass @UtilityClass
public class ConfigFile { public class ConfigFileUtils {
private static final Properties CONFIG = new Properties(); private static final Properties CONFIG = new Properties();
static { static {
@ -20,7 +20,7 @@ public class ConfigFile {
private static void loadConfig() { private static void loadConfig() {
try (InputStream resourceAsStream = ConfigFile.class.getClassLoader().getResourceAsStream("application.properties")) { try (InputStream resourceAsStream = ConfigFileUtils.class.getClassLoader().getResourceAsStream("application.properties")) {
CONFIG.load(resourceAsStream); CONFIG.load(resourceAsStream);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@ -0,0 +1,48 @@
package ru.charm.back.utils;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import ru.charm.back.dto.Query;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
@UtilityClass
public class ConnectionManager {
public static final String URL = ConfigFileUtils.get("app.datasource.url");
public static final String USER = ConfigFileUtils.get("app.datasource.username");
public static final String PASSWORD = ConfigFileUtils.get("app.datasource.password");
public static final String DRIVER = ConfigFileUtils.get("app.datasource.driver");
private static final String FETCH_SIZE_STR = ConfigFileUtils.get("app.datasource.fetch-size");
public static final int FETCH_SIZE = Integer.parseInt(FETCH_SIZE_STR != null ? FETCH_SIZE_STR : "100");
private static final String MAX_ROWS_STR = ConfigFileUtils.get("app.datasource.max-rows");
public static final int MAX_ROWS = Integer.parseInt(MAX_ROWS_STR != null ? MAX_ROWS_STR : "1000");
private static final String QUERY_TIMEOUT_STR = ConfigFileUtils.get("app.datasource.query-timeout");
public static final int QUERY_TIMEOUT = Integer.parseInt(QUERY_TIMEOUT_STR != null ? QUERY_TIMEOUT_STR : "10");
static {
if (DRIVER != null) {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASSWORD);
}
public static PreparedStatement getPreparedStmt(Connection conn, Query query) throws SQLException {
PreparedStatement stmt = conn.prepareStatement(query.sql());
List<Object> args = query.args();
for (int i = 0; i < args.size(); i++) {
stmt.setObject(i + 1, args.get(i));
}
return stmt;
}
}

View File

@ -0,0 +1,25 @@
package ru.charm.back.utils;
import lombok.experimental.UtilityClass;
import java.sql.Date;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
@UtilityClass
public class DateTimeUtils {
public static int getAge(LocalDate birthDate) {
return Math.toIntExact(ChronoUnit.YEARS.between(birthDate, LocalDate.now()));
}
public static Date getPastDate(int age) {
return Date.valueOf(LocalDate.now().minusYears(age));
}
public static boolean isValidAge(LocalDate birthDate) {
if (birthDate == null) return false;
int age = getAge(birthDate);
return age > 18 && age < 100;
}
}