Duvida em como adicionar varios produtos num pedido

Estou tentando desenvolver um sistema em que:

1 - Um cliente fornece uma quantidade de materia prima e armazena em seu estoque (são vários clientes, cada um com seu estoque)
2 - O cliente escolhe qual materia-prima vai utilizar e qual quantia (pode ser apenas um ou vários itens, mas cada item é específico)
3 - É formado uma ordem de serviço com a materia-prima que o cliente escolheu, o que dá baixa no estoque do cliente, mas mantem um registro do que foi usado

Não sei como desenvolver a relação no banco de dados para chegar a solução, visto que não é adicionado apenas um, mas vários produtos na ordem de serviço e tenho que manter um registro do que foi usado.

Agradeço qualquer ajuda.

Pedido com os dados do pedido e uma lista de ItemPedido.

ItemPedido tem o produto, quantidade e algumas pessoas colocam o preço também.

Produto tem preço, estoque, nome, descricao etc.

Eu sei que desenhando fica melhor para entender como é isso,mas a preguiça não deixa. Mas fica mais ou menos assim. Produto é ligado ao itemPedido e itemPedido ligado ao pedido.
A quantidade que está no itemPedido, você retira do estoque.

Muito grato pela dica ErickRAR, ajudou de verdade.

Mas eu ainda estou com um probleminha, cada item tem características específicas (cor, tamanho entre outros).

Gostei mesmo da dica do desenho. Segue um anexo.


Bem, meus conhecimento nisso são acadêmicos, não sei como é numa empresa de verdade, mas vamos lá:
Pensando no banco:

Estoque - id, fk_cliente.

Cliente - id, nome… fk_estoque.

Materia prima só pode pertencer a um cliente? Se sim:
Materia_prima- id, nome, descricao,…,quantidade_estoque, fk_cliente;

OrdemServico - id,dataInicioPedido,dataFinalPedido,… fk_cliente

ITemServico - id,fk_materia_prima,fk_pedido, quantidade,cor,tamanho…

Agora só colocar os outros campos que voce precisa. Pela tabela de ItemServico, você sabe qual pedido ele pertence, e como pedido tem as datas, saberá o período que foi utilizado.

Se precisar de ajuda para as classes no java, só falar.

edit: No java, é só fazer as classes. As que a tabela possuem fk de outra classe, você terá que fazer assim(Estoque por exemplo)

public class Estoque{
  private int id;
  private Cliente cliente;

Na ordem, é só colocar o List ou Set.

Fiz um exemplo parecido com esse, mas no caso de uma Biblioteca, onde na locação poderia inserir vários livros, veja como ficou as classes abaixo Locação e Item Locação.

Veja abaixo as classes DAO e Controller, espero que te ajude

Classe ItemLocacaoController

package controller;


import dao.ItemLocacaoDAO;
import java.util.List;
import model.ItemLocacao;
import model.Livro;



public class ItemLocacaoController {

    private ItemLocacaoDAO dao;
 
//apenas uns metodos que possa ser util para você   
    // método para cadastrar os itens
    public boolean cadastrar(ItemLocacao item) throws Exception{
        dao = new ItemLocacaoDAO();
        if(item != null){
            dao.salvar(item);
            return true;
        }else{
            return false;
        }
    }

  


    // método para obter ulltimo codigo do item
    public int getUltimoCodigo() throws Exception{
        dao = new ItemLocacaoDAO();
        return dao.getUltimoCodigo() + 1;
    }

    // método para retornar a lista de itens cadastrados
    public List<Livro> getTodosItens() throws Exception{
        dao = new ItemLocacaoDAO();
        return dao.todosItens();
    }

    public boolean alterar(ItemLocacao item) throws Exception{
        dao = new ItemLocacaoDAO();
        if(item != null){
            dao.atualizar(item);
            return true;
        }else{
            return false;
        }
    }

    public boolean excluir(ItemLocacao item) throws Exception{
        dao = new ItemLocacaoDAO();
        if(item != null){
            dao.excluir(item);
            return true;
        }else{
            return false;
        }
    }

    public boolean alterarSituacaoLivroParaDisponível(Livro book) throws Exception{ 
        dao = new ItemLocacaoDAO();
        if(book != null){
            dao.alterarSituacaoLivroParaDisponível(book);
            return true;
        }else{
            return false;
        }
    }

public boolean alterarSituacaoLivroParaEmprestado(Livro book) throws Exception{
        dao = new ItemLocacaoDAO();
        if(book != null){
            dao.alterarSituacaoLivroParaEmprestado(book);
            return true;
        }else{
            return false;
        }
    }



// método para pesquisar usuario qu esta com o livro, retorna o nome
    public String UsuarioComLivro(int codigoDoLivro) throws Exception{
        dao = new ItemLocacaoDAO();
        String nome = dao.UsuarioComLivro(codigoDoLivro);
      
            return nome;
        
    }
    
   // método para pesquisar usuario qu esta com o livro, retorna a matricula
    public int UsuarioComLivro2(int codigoDoLivro) throws Exception{
        dao = new ItemLocacaoDAO();
      int matricula = dao.UsuarioComLivro2(codigoDoLivro);
      
            return matricula;
        
    }
}

Classe ItemLocacaoDAO:

package dao;

import util.ConnectionFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import model.ItemLocacao;
import model.Livro;

public class ItemLocacaoDAO {

    // declaração de variável de instância
    private Connection conn;

    // construtor
    public ItemLocacaoDAO() throws Exception {
        try {
            this.conn = ConnectionFactory.getConnection();
        } catch (Exception exception) {
            throw new Exception(exception.getMessage());
        }
    }

    public boolean verifica(Livro livro) throws Exception { //função que verifica se o livro esta disponivel
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // variável para armazenar a referência de ResultSet
        ResultSet rs = null;
        try {
            // obtém instância e configura o PreparedStatement
            ps = this.conn.prepareStatement("select * from itemlocacao where codigodolivro=? and datadevolucao is null");
            // executa a instrução e armazena o resultado em ResultSet
            ps.setInt(1, livro.getCodigoDoLivro());
            rs = ps.executeQuery();
            boolean existe = false;
            while (rs.next()) {
                existe = true;


            }
            return existe;
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException.getMessage());
        
        }


    }
    

    // método para salvar os dados do objeto ItemLocacao
    public void salvar(ItemLocacao item) throws Exception {
        // variável para armazenar referência do PreparedStatement
        PreparedStatement ps = null;
        // verifica se item é null
        if (item == null) {
            throw new Exception("Erro: Item não pode ser nulo.");
        }
        Livro book = new Livro();
        book.setCodigoDoLivro(item.getCodigoDoLivro());
        if (verifica(book)) {
            throw new Exception("Erro:Livro já emprestado.");
        }
        try {
            String SQL = "INSERT INTO itemlocacao(codigoDoLivro,idLocacao,dataprevisaodevolucao,datadevolucao) "
                    + "VALUES( ?, ?, ?, ?)";
            ps = this.conn.prepareStatement(SQL);
            ps.setInt(1, item.getCodigoDoLivro());
            ps.setInt(2, item.getIdLocacao());
            ps.setDate(3, (java.sql.Date) item.getDataPrevisaoDevolucao());
            ps.setDate(4, (java.sql.Date) item.getDataDevolucao());


            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao inserir dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }
    
    // método para atualizar dados do ItemLocacao(seta a datadevolucao), utilizado na devolução
        public void atualizar(ItemLocacao item) throws Exception {
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // verifica se item é nulo
        if (item == null) {
            throw new Exception("Erro: livro não pode ser nulo.");
        }
        try {
            String SQL = "UPDATE itemlocacao (codigoDoLivro=?,idLocacao=?,dataprevisaodevolucao=?,datadevolucao=?) "
                    + " WHERE codigodolivro=?";
            // obtém instância de PreparedStatement
            ps = this.conn.prepareStatement(SQL);
            // configura a instrução
            ps.setInt(1, item.getCodigoDoLivro());
            ps.setInt(2, item.getIdLocacao());
            ps.setDate(3, (java.sql.Date) item.getDataPrevisaoDevolucao());
            ps.setDate(4, (java.sql.Date) item.getDataDevolucao());

            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao atualizar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }
    // método para excluir dados do Livro

    public void excluir(ItemLocacao item) throws Exception {
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // verifica se item é nulo
        if (item == null) {
            throw new Exception("Erro: item não pode ser nulo.");
        }
        try {
            // obtém instância de PreparedStatement
            ps = this.conn.prepareStatement("DELETE FROM itemlocacao "
                    + "WHERE iditem_locacao=?");
            // configura a instrução
            ps.setInt(1, item.getIdItemlocacao());
            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao excluir dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }

    // método para listar os dados de todos itens
    public List todosItens() throws Exception {
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // variável para armazenar a referência de ResultSet
        ResultSet rs = null;
        try {
            // obtém instância e configura o PreparedStatement
            ps = this.conn.prepareStatement("SELECT * FROM itemlocacao");
            // executa a instrução e armazena o resultado em ResultSet
            rs = ps.executeQuery();
            List<ItemLocacao> lista = new ArrayList<ItemLocacao>();
            while (rs.next()) {
                int idItemLocacao = rs.getInt(3);
                int idLocacao = rs.getInt(2);
                int codigoDoLivro = rs.getInt(1);
                Date DataPrevisaoDevolucao = rs.getDate(4);
                Date DataDevolucao = rs.getDate(5);




                // instancia um novo item e insere na lista
                lista.add(new ItemLocacao(codigoDoLivro, idLocacao, idItemLocacao, DataPrevisaoDevolucao, DataDevolucao));
            }
            return lista;
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }
    }

    public int getUltimoCodigo() throws Exception {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            String SQL = "SELECT * FROM itemlocacao ORDER BY iditem_locacao DESC LIMIT 1";
            ps = this.conn.prepareStatement(SQL);
            rs = ps.executeQuery();
            int codigo = 0;
            if (rs.next()) {
                codigo = rs.getInt(1);
            }
            return codigo;
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException);
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }
    }

    public void alterarSituacaoLivroParaDisponível(Livro book) throws Exception {

        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // verifica se item é nulo
        if (book == null) {
            throw new Exception("Erro: livro não pode ser nulo.");
        }

        try {
            String SQL = "UPDATE livro SET situacao = 'Disponível' WHERE codigoDoLivro = ?";
            // obtém instância de PreparedStatement
            ps = this.conn.prepareStatement(SQL);
            // configura a instrução
            ps.setInt(1, book.getCodigoDoLivro());


            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao atualizar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }

    public void alterarSituacaoLivroParaEmprestado(Livro book) throws Exception {

        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // verifica se item é nulo
        if (book == null) {
            throw new Exception("Erro: livro não pode ser nulo.");
        }

        try {
            String SQL = "UPDATE livro SET situacao = 'Emprestado' WHERE codigoDoLivro = ?";
            // obtém instância de PreparedStatement
            ps = this.conn.prepareStatement(SQL);
            // configura a instrução
            ps.setInt(1, book.getCodigoDoLivro());


            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao atualizar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }
    
     public void devolver(ItemLocacao item) throws Exception {

        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // verifica se item é nulo
        if (item == null) {
            throw new Exception("Erro: item não pode ser nulo.");
        }
        Livro book = new Livro();
        book.setCodigoDoLivro(item.getCodigoDoLivro());
        if (verifica(book)==false) {
            throw new Exception("Erro:Livro não emprestado.");
        }
        try {
            String SQL = "UPDATE itemlocacao SET datadevolucao = now() WHERE codigoDoLivro = ? and datadevolucao is null";//now pega a data do banco atual
            // obtém instância de PreparedStatement
            ps = this.conn.prepareStatement(SQL);
            // configura a instrução
            ps.setInt(1, item.getCodigoDoLivro());


            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao atualizar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }
       public double calculaMulta(ItemLocacao item) throws Exception {
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // variável para armazenar a referência de ResultSet
        ResultSet rs = null;
        try {
            // obtém instância e configura o PreparedStatement
            ps = this.conn.prepareStatement("select case when cast(now()as Date) - dataprevisaodevolucao >= 0 then cast(now()as Date) - dataprevisaodevolucao else 0 "
                    + "end from itemlocacao where  datadevolucao is null and codigodolivro=?");
            ps.setInt( 1,item.getCodigoDoLivro());
            // executa a instrução e armazena o resultado em ResultSet
            rs = ps.executeQuery();
            double multa=0;
            while (rs.next()) {
                multa += rs.getDouble(1);
            }
            return multa;
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }
       }
       
     // método para mostrar o nome do usuário que está com o livro que vai ser devolvido.
    public String UsuarioComLivro(int codigoDoLivro) throws Exception {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = this.conn.prepareStatement("SELECT u.nome  from usuario u, itemlocacao il, "
                    + "locacao lo WHERE u.matricula = lo.matricula  and lo.idlocacao = il.idlocacao and il.datadevolucao is null and il.codigodolivro=?;");
            ps.setInt(1, codigoDoLivro);
            rs = ps.executeQuery();
            String nome = "";
            while (rs.next()) {
                              
               nome=(rs.getString(1));
               
              
            }
            return nome;
            
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException);
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }
    }
        // método para mostrar a matricula do usuário que está com o livro que vai ser devolvido.
       public int UsuarioComLivro2(int codigoDoLivro) throws Exception {
        int matricula=0;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = this.conn.prepareStatement("SELECT u.matricula  from usuario u, itemlocacao il, "
                    + "locacao lo WHERE u.matricula = lo.matricula  and lo.idlocacao = il.idlocacao and il.datadevolucao is null and il.codigodolivro ="+codigoDoLivro);
          //  ps.setInt(1, codigoDoLivro);
            rs = ps.executeQuery();
          
            if (rs.next()) {
                              
               matricula=(rs.getInt(1));
               
              
            }
            System.out.println("reorno mat:"+matricula);
            return matricula;
            
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException);
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }
    }
}

Classe LocacaoController

package controller;



import dao.LocacaoDAO;
import java.util.List;
import model.Livro;
import model.Locacao;
import model.Locacao_itemLocacao;



public class LocacaoController {

    private LocacaoDAO dao;
    
    // método para cadastrar os livro
    public boolean cadastrar(Locacao loc) throws Exception{
        dao = new LocacaoDAO();
        if(loc != null){
            dao.salvar(loc);
            return true;
        }else{
            return false;
        }
    }

  

    // método para pesquisar locacao pelo id
    public List pesquisar(int idLocacao) throws Exception{
        dao = new LocacaoDAO();
        List<Livro> lista = dao.listaCodigo(idLocacao);
        if(!lista.isEmpty()){
            return lista;
        }else{
            return null;
        }
    }

    // método para obter a último idLocacao
    public int getUltimoCodigo() throws Exception{
        dao = new LocacaoDAO();
        return dao.getUltimoCodigo() + 1;
    }

    // método para retornar a lista de livros cadastrados
    public List<Locacao> getTodasLocacoes() throws Exception{
        dao = new LocacaoDAO();
        return dao.todasLocacoes();
    }

    public boolean alterar(Locacao loc) throws Exception{
        dao = new LocacaoDAO();
        if(loc != null){
            dao.atualizar(loc);
            return true;
        }else{
            return false;
        }
    }

    public boolean excluir(Locacao loc) throws Exception{
        dao = new LocacaoDAO();
        if(loc != null){
            dao.excluir(loc);
            return true;
        }else{
            return false;
        }
    }
    
     // método para retorna a lista juntos
    public List<Locacao_itemLocacao> getListarJuntos(int idLocacao) throws Exception{
        dao = new LocacaoDAO();
        return dao.listarJuntos(idLocacao);
    }
    


}

Classe LocacaoDao

package dao;

import util.ConnectionFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import model.Livro;
import model.Locacao;
import model.Locacao_itemLocacao;

public class LocacaoDAO {

    // declaração de variável de instância
    private Connection conn;

    // construtor
    public LocacaoDAO() throws Exception {
        try {
            this.conn = ConnectionFactory.getConnection();
        } catch (Exception exception) {
            throw new Exception(exception.getMessage());
        }
    }

    // método para salvar os dados da locacao
    public void salvar(Locacao loc) throws Exception {
        // variável para armazenar referência do PreparedStatement
        PreparedStatement ps = null;
        // verifica se loc é null
        if (loc == null) {
            throw new Exception("Erro: Locacao não pode ser nulo.");
        }
        try {
            String SQL = "INSERT INTO locacao(matricula, datalocacao) "
                    + "VALUES( ?, ?)";
            ps = this.conn.prepareStatement(SQL);
            ps.setInt(1, loc.getMatricula());
            ps.setDate(2, new java.sql.Date(loc.getDataLocacao().getTime()));;



            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao inserir dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }

    // método para atualizar dados da locacao
    public void atualizar(Locacao loc) throws Exception {
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // verifica se loc é nulo
        if (loc == null) {
            throw new Exception("Erro: livro não pode ser nulo.");
        }
        try {
            String SQL = "UPDATE locacao(matricula=?,datalocacao=?) "
                    + " WHERE locacao=?";
            // obtém instância de PreparedStatement
            ps = this.conn.prepareStatement(SQL);
            // configura a instrução
            ps.setInt(1, loc.getMatricula());
            ps.setDate(2, (java.sql.Date) loc.getDataLocacao());

            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao atualizar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }

    // método para excluir a locacao
    public void excluir(Locacao loc) throws Exception {
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // verifica se loc é nulo
        if (loc == null) {
            throw new Exception("Erro: livro não pode ser nulo.");
        }
        try {
            // obtém instância de PreparedStatement
            ps = this.conn.prepareStatement("DELETE FROM locacao "
                    + "WHERE idLocacao=?");
            // configura a instrução
            ps.setInt(1, loc.getIdLocacao());
            // executa a instrução
            ps.executeUpdate();
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao excluir dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps);
        }
    }

    // método para listar os dados de todas locações
    public List todasLocacoes() throws Exception {
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // variável para armazenar a referência de ResultSet
        ResultSet rs = null;
        try {
            // obtém instância e configura o PreparedStatement
            ps = this.conn.prepareStatement("SELECT * FROM locacao");
            // executa a instrução e armazena o resultado em ResultSet
            rs = ps.executeQuery();
            List<Locacao> lista = new ArrayList<Locacao>();
            while (rs.next()) {
                int idLocacao = rs.getInt(1);
                int matricula = rs.getInt(2);
                Date dataLocacao = (java.sql.Date) rs.getDate(3);




                // instancia um novo usuario e insere na lista
                lista.add(new Locacao(idLocacao, matricula, dataLocacao));
            }
            return lista;
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }
    }

    // método para consultar Locacao através do idLocacao
    public List listaCodigo(int idLocacao) throws Exception {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = this.conn.prepareStatement("SELECT * FROM locacao WHERE idLocacao=?");
            ps.setInt(1, idLocacao);
            rs = ps.executeQuery();
            List<Locacao> lista = new ArrayList<Locacao>();
            while (rs.next()) {
                Locacao loc = new Locacao();
                loc.setIdLocacao(rs.getInt(1));
                loc.setMatricula(rs.getInt(2));
                loc.setDataLocacao(rs.getDate(3));



                lista.add(loc);
            }
            return lista;
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException);
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }

    }

    public int getUltimoCodigo() throws Exception {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            String SQL = "select last_value from locacao_idLocacao_seq";
            ps = this.conn.prepareStatement(SQL);
            rs = ps.executeQuery();
            int codigo = 0;
            if (rs.next()) {
                codigo = rs.getInt(1);
            }
            return codigo;
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException);
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }
    }

    // método para listar os dados juntos, utilizado na tabela da tela locação
    public List listarJuntos(int idLocacao) throws Exception {
        // variável para armazenar a referência de PreparedStatement
        PreparedStatement ps = null;
        // variável para armazenar a referência de ResultSet
        ResultSet rs = null;
        try {

            String SQL = "SELECT li.codigoDolivro, li.titulo, lo.DataLocacao, il.DataPrevisaoDevolucao from livro li, itemlocacao il, locacao lo WHERE li.codigodolivro = il.codigodolivro   and lo.idlocacao = il.idlocacao and lo.idlocacao=?";
            // executa a instrução e armazena o resultado em ResultSet
            ps = this.conn.prepareStatement(SQL);
            ps.setInt(1, idLocacao);
            rs = ps.executeQuery();


            List<Locacao_itemLocacao> lista = new ArrayList<Locacao_itemLocacao>();

            while (rs.next()) {
                Locacao_itemLocacao l = new Locacao_itemLocacao();
                l.setCodigoDoLivro(rs.getInt(1));
                l.setTitulo(rs.getString(2));
                l.setDataLocacao(rs.getDate(3));
                l.setDataPrevisaoDevolucao(rs.getDate(4));


                lista.add(l);
            }
            return lista;
        } catch (SQLException sqlException) {
            throw new Exception("Erro ao consultar dados: "
                    + sqlException.getMessage());
        } finally {
            ConnectionFactory.closeConnection(conn, ps, rs);
        }
    }
}

Acredito que se você entender este codigo, certamente você consiguirá fazer o seu, visto que a ideia é a mesma.

Até mais.

O meu Banco ficou assim:
create table Livro (
codigoDoLivro serial PRIMARY KEY,
autor varchar(80),
assunto varchar(80),
situacao varchar(80),
titulo varchar(80),
isbn varchar(80),
numPaginas varchar(10),
ano varchar(5),
classificacao varchar(10),
notacao varchar(10),
editora varchar(50),
local varchar(50)
);

create table Usuario (
Matricula serial PRIMARY KEY,
Nome varchar(80),
DataNasc date,
RG varchar(100),
Endereco varchar(80),
Cidade varchar(50),
Email varchar(50),
Telefone varchar(15),
Profissao varchar(50),
Multa numeric(7,2)
);

create table Locacao (
IdLocacao serial PRIMARY KEY,
Matricula int,
DataLocacao date,
FOREIGN KEY(Matricula) REFERENCES Usuario (Matricula)
);

create table ItemLocacao (
idItem_locacao serial primary key,
codigoDoLivro int,
IdLocacao int,
DataPrevisaoDevolucao date,
DataDevolucao date,
FOREIGN KEY(codigoDoLivro) REFERENCES Livro(codigoDoLivro),
FOREIGN KEY(IdLocacao) REFERENCES Locacao(IdLocacao)

);