I'm new to Java and Spring and I am doing my first rest service. I've encountered a problem to which I cannot find an answer.
I generated entities using Jooq with pojos and daos
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<version>3.16.6</version>
<executions>
...
</executions>
<configuration>
<jdbc>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://localhost:5432/spring</url>
<user>postgres</user>
<password>${env.PGPASSWORD}</password>
</jdbc>
<generator>
<name>org.jooq.codegen.JavaGenerator</name>
<database>
...
</database>
<target>
<packageName>com.example.otrtesttask.jooq</packageName>
<directory>target/generated-sources/jooq</directory>
</target>
<generate>
<pojos>true</pojos>
<daos>true</daos>
<records>true</records>
</generate>
</generator>
</configuration>
</plugin>
My database structure:
CREATE TABLE branch(id SERIAL PRIMARY KEY, title VARCHAR(100));
CREATE TABLE position(id SERIAL PRIMARY KEY, title VARCHAR(30));
CREATE TABLE employee
(
id SERIAL PRIMARY KEY,
manager_id INTEGER REFERENCES employee (id),
position_id INTEGER REFERENCES position (id) NOT NULL,
full_name VARCHAR(50) NOT NULL,
branch_id INTEGER REFERENCES branch (id) NOT NULL);
CREATE TABLE task
(
id SERIAL PRIMARY KEY,
priority SMALLINT NOT NULL,
description VARCHAR(200) NOT NULL,
employee_id INT REFERENCES employee (id) NOT NULL);
Then I made Controller that calls Service that calls Repository to invoke CRUD operations. And it works perfectly fine, but I want to get position title along with id, etc. So I made a DTO:
@Data
public class EmployeeDto {
private Integer id;
private Integer managerId;
private Integer positionId;
private String fullName;
private Integer branchId;
private Employee manager;
private Position position;
private Branch branch;
}
After that I made a mapper that converts Employee to EmplyeeDto. I've been told that the best way to get nested data (like position title) is to use DAO fetchOnyById function.
@Service
public class MappingUtils {
EmployeeDao employeeDao = new EmployeeDao();
PositionDao positionDao = new PositionDao();
BranchDao branchDao = new BranchDao();
public EmployeeDto mapToEmployeeDto(Employee employee) {
EmployeeDto dto = new EmployeeDto();
dto.setId(employee.getId());
dto.setBranchId(employee.getBranchId());
dto.setPositionId(employee.getPositionId());
dto.setFullName(employee.getFullName());
dto.setManagerId(employee.getManagerId());
dto.setManager(employeeDao.fetchOneById(employee.getManagerId()));
dto.setPosition(positionDao.fetchOneById(employee.getPositionId()));
dto.setBranch(branchDao.fetchOneById(employee.getBranchId()));
return dto;
}
And I map entities inside Repository like this:
@Repository
@RequiredArgsConstructor
public class EmployeeRepository {
@Autowired
private final DSLContext dsl;
private final MappingUtils mappingUtils;
public List<EmployeeDto> findAll(Condition condition) {
return dsl.selectFrom(Tables.EMPLOYEE)
.where(condition)
.fetchInto(Employee.class)
.stream().map(mappingUtils::mapToEmployeeDto)
.collect(Collectors.toList());
}
}
And it works fine until it gets to the dao fetch function. It throws an exception org.jooq.exception.DetachedException: Cannot execute query. No JDBC Connection configured
.
Once I remove the dao functions the get query returns nice response with manager, position and branch set to null.
What am I doing wrong here? And how to provide necessary connection?
==UPD== My application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/spring
spring.datasource.username=postgres
spring.datasource.password=${PGPASSWORD}
spring.liquibase.change-log=classpath:liquibase/changelog.sql
CodePudding user response:
The problem is that your DAO classes aren't attached to a jOOQ Configuration
. You just created them like this:
EmployeeDao employeeDao = new EmployeeDao();
But you have to create them like this:
EmployeeDao employeeDao = new EmployeeDao(configuration);
You can also configure the code generator to generate Spring annotations and then inject the DAOs to your class. The configuration would be:
<configuration>
<generator>
<generate>
<springAnnotations>true</springAnnotations>
<!-- ... -->
And then:
@Service
public class MappingUtils {
@Autowired
EmployeeDao employeeDao;
@Autowired
PositionDao positionDao;
@Autowired
BranchDao branchDao;
// ...