Postgres会列出特定Employee行的所有表字段吗?

时间:2020-05-17 09:45:39

标签: postgresql

从链接Postgres to fetch the list having comma separated values中获取参考,我想编写一个查询,该查询将员工电子邮件表字段作为特定员工的列表。为了使Spring Batch能够从结果集中简单地匹配它,并创建一个POJO / Model类,例如为Employee类列出电子邮件?,这是必需的?

这可能吗?

select c.*, ce.*, string_agg(ce.email, ',') as emails
from root.employee c
full outer join root.employee_email ce
    on c.employee_id = ce.employee_id
group by
    c.employee_id, ce.employee_email_id
order by
    c.employee_id
limit 1000
offset 0;

1 个答案:

答案 0 :(得分:0)

您的问题是批处理领域中的常见问题,在Spring Batch中,它称为“基于查询的驱动项读取器”,您可以在here中找到有关此问题的更多信息。

基本上,您可以在阅读器中检索联系人,并在处理器中向其中添加电子邮件列表。

    @Bean(destroyMethod = "")
    public JdbcCursorItemReader<Employee> employeeReader(DataSource dataSource) {
        JdbcCursorItemReader<Employee> ItemReader = new JdbcCursorItemReader<>();
        ItemReader.setDataSource(dataSource);
        ItemReader.setSql("SELECT * FROM employee.employee C ");
        ItemReader.setRowMapper(new EmployeeRowMapper());
        return ItemReader;
    }

    @Bean
    public ItemProcessor<Employee, Employee> settlementHeaderProcessor(JdbcTemplate jdbcTemplate){

        return item -> {
      root.EMPLOYEE_EMAIL CE WHERE ce.employee_id = ? ",
                    new Object[]{item.getId()},
                    new RowMapper<String>() {
                        @Override
                        public String mapRow(ResultSet resultSet, int i) throws SQLException {
                            return resultSet.getString("EMAIL");
                        }
                    });

            item.setEmails(emails);

            return item;
        };
    }

PS :如果您有很多联系人,这可能会出现一些性能问题,因为对于每个联系人项目,您将访问数据库以检索电子邮件。

还有另一种优化的方法,方法是创建一个自定义阅读器,该阅读器将返回联系人的列表(例如1000 x 1000),并创建一个处理器,使他们的电子邮件内容更加丰富。这样,您将再次为每1000个联系项目访问数据库。

在您的阅读器中,每页检索一个唯一的雇员页面列表(说您的页面长1000)。 在您的1000名员工的处理器中,您可以在一个查询中检索所有电子邮件。

然后为每个员工设置上一个查询中检索到的电子邮件。

示例可能如下:

public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Integer> {
}

@Getter
class EmployeeVO {
    private Long employeeId;
    private String email;

    EmployeeVO(Long employeeId, String email) {
        this.employeeId= employeeId;
        this.email = email;
    }
}

public class EmployeeListReader implements ItemReader<List<Employee>> {

    private final static int PAGE_SIZE = 1000;

    private final EmployeeRepository employeeRepository;
    private int page = 0;

    public EmployeeListReader(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }


    public List<Employee> read() throws Exception {
        Page<Employee> employees = employeeRepository.findAll(PageRequest.of(page, PAGE_SIZE));
        page++;

        return employees.getContent();
    }
}

@Bean 
EmployeeListReader reader(){
    return new EmployeeListReader(this.employeeRepository);
}

@Bean
public ItemProcessor<List<Employee>, List<Employee>> settlementHeaderProcessor(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {

    return item -> {

        List<Long> employeesIds = item.stream().map(Employee::getId).collect(Collectors.toList());

        SqlParameterSource parameters = new MapSqlParameterSource("ids", employeesIds);

        List<ContactVO> emails = namedParameterJdbcTemplate
                                    .query("SELECT CE.employeeId, CE.EMAIL FROM employee_EMAIL CE WHERE ce.contact_id IN  (:ids) ",
                parameters,
                new RowMapper<ContactVO>() {
                    @Override
                    public ContactVO mapRow(ResultSet resultSet, int i) throws SQLException {
                        return new ContactVO(
                                resultSet.getLong("EMPLOYEE_ID"),
                                resultSet.getString("EMAIL"));
                    }
                });

        Map<Long, List<ContactVO>> emailsByContactId = emails.stream().collect(Collectors.groupingBy(ContactVO::getContactId));

        List<Employee> newEmployeesWithEmails = Collections.unmodifiableList(item);

        newEmployeesWithEmails.forEach(employee -> {
            employee.setEmails(emailsByContactId.get(employee.getId()).stream().map(ContactVO::getEmail).collect(Collectors.toList()));
        });

        return newEmployeesWithEmails;
    };
}

希望这对您有帮助