Fórum Mapear varias tabelas com a mesma classe JPA. #447997
06/07/2013
0
Ou se tiver como alterar o nome da tabela na anotação Table(name="pedidos"), em tempo de execução também server.
EX: Tenho tabela de pedidos e pedidositens, pra ficar otimizado devido o grande volume de dados tem que ser dividida por mês, ou seja pedidos_201301, pedidos_201302, ..., o mesmo para tabela de pedidositens.
Pensei em usar herença nessas tabelas entidades, mas ai o sistema ira ter muitas classes, o que achei muito trabalhoso.
Desde já obrigado pela atenção.
Tecnologias envolvidas, JPA, JSF 2.0, PrimeFaces, Tomcat 6.
Fernando Silva
Curtir tópico
+ 0Posts
06/07/2013
Marcelo Senaga
O melhor seria o mapeamento 1x1, quanto mais classes, melhor. Cada classe deve representar um conceito diferente do sistema.
Gostei + 0
06/07/2013
Fernando Silva
Então as tabelas são grandes pra postar, mas em resumo são tabelas comuns, porém todas tabelas comuns terão a mesma estrutura a exemplo destas que postei pedidos e itens. Só irei dividir pra ficar fácil a manutenção, e rápido os selects, até pra fazer limpeza de dados ficará melhor.
O melhor seria o mapeamento 1x1, quanto mais classes, melhor. Cada classe deve representar um conceito diferente do sistema.
Neste caso em 5 anos eu teria:
Pedidos 5 * 12 = 60
ItensPedidos 5 * 12 = 60
Vendas 5 * 12 = 60
ItensVendas 5 * 12 = 60
Inventario 5 * 12 = 60
Orçamento 5 * 12 = 60
OrçamentoItens 5 * 12 = 60
MovProdutos 5 * 12 = 60
Cupons 5 * 12 = 60
ItensCupons 5 * 12 = 60
Olhando para meus diagramas verifiquei que tenho estas tabelas acima pra criar e todas terão muitos registros.
O que totalizaria 600 classes entidades em 5 anos, não seria muito ?
Fico com medo de fazer algo que fique meio fora de padrão.
Gostei + 0
06/07/2013
Fernando Silva
//Aqui a de pedido as mensais será igual
public class ComPedido7 implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idcodigo7")
private Integer idcodigo7;
@JoinColumn(name = "fkfornecedor7", referencedColumnName = "idcodigo15")
@OneToOne()
private GerFornecedor15 fkfornecedor7;
@Basic(optional = false)
@Column(name = "fkempresa7")
private int fkempresa7;
@Column(name = "fkusuinc7")
private Integer fkusuinc7;
@Column(name = "fkusualt7")
private Integer fkusualt7;
@Basic(optional = false)
@Column(name = "datainc7")
@Temporal(TemporalType.TIMESTAMP)
private Date datainc7;
@Column(name = "dataalt7")
@Temporal(TemporalType.TIMESTAMP)
private Date dataalt7;
@Column(name = "preventrega7")
@Temporal(TemporalType.DATE)
private Date preventrega7;
@Column(name = "obs7")
private String obs7;
// @Max(value=?) @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
@Column(name = "vlrfrete7")
private BigDecimal vlrfrete7;
@Basic(optional = false)
@Column(name = "statusbaixa7")
private String statusbaixa7;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "comPedido7")
private List<ComPedidoItens8> comPedidoItens8List;
@JoinColumn(name = "fkconfigpedido7", referencedColumnName = "idcodigo9")
@ManyToOne(optional = false)
private ComConfpedido9 fkconfigpedido7;
@Transient
private String nomeFornecedor;
@Transient
private Integer configPedidoString;
}
//Aqui as tabelas de itensPedidos
public class ComPedidoItens8 implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected ComPedidoItens8PK comPedidoItens8PK;
@Basic(optional = false)
@Column(name = "seqitem8")
private int seqitem8;
// @Max(value=?) @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
@Column(name = "qtditem8")
private BigDecimal qtditem8;
@Column(name = "qtdembitem8")
private Integer qtdembitem8;
@Column(name = "custoitem8")
private BigDecimal custoitem8;
@Column(name = "ipiitemper8")
private BigDecimal ipiitemper8;
@Column(name = "icmsitem8")
private BigDecimal icmsitem8;
@Column(name = "stitem8")
private BigDecimal stitem8;
@Column(name = "databaixa8")
@Temporal(TemporalType.TIMESTAMP)
private Date databaixa8;
@Basic(optional = false)
@Column(name = "statusbaixa8")
private String statusbaixa8;
@Column(name = "qtdbaixada8")
private BigDecimal qtdbaixada8;
@Column(name = "custobaixado8")
private BigDecimal custobaixado8;
@JoinColumn(name = "fkitem8", referencedColumnName = "idcodigo1", insertable = false, updatable = false)
@ManyToOne(optional = false)
private EstProdutos1 estProdutos1;
@JoinColumn(name = "idfkpedido8", referencedColumnName = "idcodigo7", insertable = false, updatable = false)
@ManyToOne(optional = false)
private ComPedido7 comPedido7;
}
Gostei + 0
07/07/2013
Marcelo Senaga
http://ossevagolb.blogspot.com.br/2010/12/mapear-e-preciso-xml-e-so-um-meio.html
Procure sobre mapeamento dinamico em hibernate.
Gostei + 0
07/07/2013
Fernando Silva
http://ossevagolb.blogspot.com.br/2010/12/mapear-e-preciso-xml-e-so-um-meio.html
Procure sobre mapeamento dinamico em hibernate.
Seguinte olhei as soluções que indicou, mas pensei em usar outro recurso direto no banco.
1 - Particionar tabelas;
2 - Colocar triggers para direcionar os inserts para as tabelas certas.
O que você acha ??
Gostei + 0
07/07/2013
Anthony Accioly
Seguinte olhei as soluções que indicou, mas pensei em usar outro recurso direto no banco.
1 - Particionar tabelas;
2 - Colocar triggers para direcionar os inserts para as tabelas certas.
O que você acha ??
Uma maneira de alcançar o resultado almejado seria criar views e mapeá-las para suas respectivas entidades. e.g., uma view com a união de todas as tabelas antigas apenas para consultas históricas (não performático) e outra view "apontando" para a tabela física mais atual para operações de escrita e o grosso das consultas. Do lado do JPA você teria apenas duas entidades PedidoHistorico (apontando para a view da união) e PedidoAtual.
Pensando no Oracle, você pode criar jobs (http://docs.oracle.com/cd/E11882_01/server.112/e25494/scheduse002.htm) para atualizar as duas views mensalmente, de maneira que tudo fica 100% transparente para a aplicação.
Observação: Criar novas tabelas para diminuir o número de linhas analisado por consulta é, de certa maneira, reinventar a roda (e fazer manualmente algo que poderia ser automatizado). O nome do que vocês estão fazendo é particionamento horizontal (http://en.wikipedia.org/wiki/Partition_(database)); mais especificamente, particionamento por range de datas distribuídos em um único nó do banco de dados [o que não é escalável no longo prazo). No caso, se você puder adaptar o mecanismo de armazenamento à aplicação ao invés de adaptar a aplicação ao mecanismo de armazenamento, há várias opções que estendem a funcionalidade básica do ORM para trabalhar com particionamento. Seguem exemplos:
Hibernate Shards: [url]http://www.hibernate.org/subprojects/shards.html[/url]
Eclipse Link:[url]http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Data_Partitioning[/url]
Gostei + 0
07/07/2013
Marcelo Senaga
Seguinte olhei as soluções que indicou, mas pensei em usar outro recurso direto no banco.
1 - Particionar tabelas;
2 - Colocar triggers para direcionar os inserts para as tabelas certas.
O que você acha ??
Uma maneira de alcançar o resultado almejado seria criar views e mapeá-las para suas respectivas entidades. e.g., uma view com a união de todas as tabelas antigas apenas para consultas históricas (não performático) e outra view "apontando" para a tabela física mais atual para operações de escrita e o grosso das consultas. Do lado do JPA você teria apenas duas entidades PedidoHistorico (apontando para a view da união) e PedidoAtual.
Pensando no Oracle, você pode criar jobs (http://docs.oracle.com/cd/E11882_01/server.112/e25494/scheduse002.htm) para atualizar as duas views mensalmente, de maneira que tudo fica 100% transparente para a aplicação.
Observação: Criar novas tabelas para diminuir o número de linhas analisado por consulta é, de certa maneira, reinventar a roda (e fazer manualmente algo que poderia ser automatizado). O nome do que vocês estão fazendo é particionamento horizontal (http://en.wikipedia.org/wiki/Partition_(database)); mais especificamente, particionamento por range de datas distribuídos em um único nó do banco de dados [o que não é escalável no longo prazo). No caso, se você puder adaptar o mecanismo de armazenamento à aplicação ao invés de adaptar a aplicação ao mecanismo de armazenamento, há várias opções que estendem a funcionalidade básica do ORM para trabalhar com particionamento. Seguem exemplos:
Hibernate Shards: [url]http://www.hibernate.org/subprojects/shards.html[/url]
Eclipse Link:[url]http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Data_Partitioning[/url]
Excelente postagem! Vou dar uma olhada no Hibernate Shards.
Gostei + 0
18/07/2013
Fernando Silva
abaixo a função.
Obrigado a todos que ajudaram.
CREATE OR REPLACE FUNCTION pedido_ajusta_insert_antes()
RETURNS trigger AS
$BODY$
DECLARE nomeTabela varchar(100);
BEGIN
nomeTabela := ('pedido_'||Trim(to_char(DATE_PART('MONTH', Date(NEW.data_pedido)),'00'))||Trim(to_char(DATE_PART('YEAR', Date(NEW.data_pedido)),'9999')));
IF (TG_OP = 'INSERT') THEN
EXECUTE 'INSERT INTO '||nomeTabela||'(id_pedido, data_pedido, id_cliente, id_vendedor) '
'VALUES ( '||nextval('pedido_id_pedido_seq'::regclass)|| ' , '||NEW.data_pedido||' , '||NEW.id_cliente||' , '||NEW.id_vendedor||' )';
return NEW;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION pedido_ajusta_insert_antes()
OWNER TO postgres;
Gostei + 0
20/07/2013
José
Caso a duvida não tenha sido sanada totalmente, peça para reabrirmos o tópico, ou fique a vontade para abrir um novo.
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)