Mas tenho uma dúvida: o seu modelo de negócio realmente precisa de herança?
Na verdade não, meu conhecimento ainda é bem limitado, por isso me pareceu o melhor caminho. Tentei fazer agora por composição, apesar de fazer total sentido, não havia pensado nisso até lembrar que o Deschamps falou tocou no assunto em um dos vídeos que assiste a alguns meses. Lembrei do termo logo depois que te respondi e fui ler sobre o conceito. Usei, deu um erro na hora de subir a aplicação: Could not determine recommended JdbcType for Java type 'dev.tadeupinheiro.apistockinputspringboot.models.ArticleModel
Não sei significa alguma coisa sem ter as classes da aplicação para entender, mas enfim, mesmo que eu consiga resolver esse erro, não acho que seria performático, salvar todas as classes em cada registro que eu fizer no db.
Vamos lá, vou tentar explicar como funciona o negócio:
Existe os ARTIGOS, que seríam os "modelos" do produto. Exemplo: Existe o artigo chamado UNIPACIFIC, que é um tipo de tecido, que tem seus atributos (nome, peso, fabricante e composição), ele não vai ser alterado, vai ser cadastro e fica lá, eventualmente se cadastraria outros artigos, mas seria em outro métodos, essa parte seria "fácil".
Existe também as CORES, o artigo UNIPACIFIC tem sua paleta de cores, que serve para ele a para outros artigos também. Se encaixa no mesmo esquema: eventualmente se cadastria outros mas não é o centro da api no momento.
Por fim, existe o ROLO, que é o ponto central aqui. O rolo possui o número(que seria o ID dele), possui tamanho, qualidade, tratamento, preço de custo e etc. A questão é que o rolo não se repete e não seria extendido por nenhuma outra classe. Terá a entrada no banco de dados e na venda teria a saída e o id não se repete. Mas o rolo também terá o artigo e seus atributos e a cor e seus atributos, exemplo: Número do rolo: 156879 (primary key) Tamanho: 100m Preço de custo: 19,00 Artigo: Unipacific Fabricante: Satanense (demais atributos do artigo) Código da cor: 5890 Cor: Azul
Então a minha intenção seria:
Salvar o rolo e seus atributos na tabela: TB_PRODUCTS_IN_STOCK, e nele ter a coluna de chave estrangeira fazendo referência para o artigo e a cor. Não salvando a classe completa dentro da tabela como seria na composição. Seria somente a referência e na hora de puxar o relatório puxar pela chave.
Caso faça diferença e possa dar uma olhada:
Repositório GITHUB: https://github.com/tadeupinheiro/api-stock-input-spring-boot/tree/Using-composition/src/main/java/dev/tadeupinheiro/apistockinputspringboot
Está na branch: Using-Composition
Você encontrou o erro "Could not determine recommended JdbcType for Java type 'dev.tadeupinheiro.apistockinputspringboot.models.ArticleModel'" porque você colocou uma classe dentro da outra. Neste caso, o JPA pensa que você quer serializar a classe em uma coluna; contudo, o Jdbc não sabe como serializar a classe ArticleModel e falha. Mas não vamos nos preocupar com isso por agora porque não é o caminho que queremos.
Lendo a sua descrição, no meu entendimento, o seu modelo de negócio fica assim:
- Cor:
- Uma Cor pode estar associada a vários Artigos.
- Rolo:
- Um Rolo está associado a apenas um Artigo.
- Um Rolo está associado a apenas um Produto.
- Artigo:
- Um Artigo está associado a apenas uma Cor.
- Um Artigo está associado a vários Rolos.
- Produto:
- Um Produto está associado a vários Rolos.
Um diagrama bidirecional ficaria assim:
+---------------+
| Artigo |
+---------------+
UmParaMuitos / \ MuitosParaUm
/ \
/ \
/ \
MuitosParaUm / \ UmParaMuitos
+---------------+ ----------------+
| Rolo | | Cor |
+---------------+ +---------------+
MuitosParaUm |
|
|
UmParaMuitos |
+---------------+
| Produto |
+---------------+
Relacionamentos bidirecionais são mais difíceis de trabalhar. Eu começaria com um diagrama unidirecional e depois mudaria para um bidirecional se houver necessidade. Fica difícil sugerir um modelo unidirecional sem saber a API do sistema, mas eu acho que você deve estar caminhando para algo assim:
+---------------+
| Artigo |
+---------------+
/ \ MuitosParaUm
/ \
/ \
/ \
MuitosParaUm / \
+---------------+ ----------------+
| Rolo | | Cor |
+---------------+ +---------------+
|
|
|
UmParaMuitos |
+---------------+
| Produto |
+---------------+
Com esse diagrama, o fluxo da API ficaria assim:
- Criar uma Cor.
- Criar um Artigo contendo sua respectiva Cor.
- Criar vários Rolos contendo seus respectivos Artigos.
- Criar um Produto contendo seus respectivos Rolos.
Neste tipo de organização, quando criamos um Produto, só precisamos dizer quais os rolos incluídos no Produto, e as informações sobre Artigo e Cor já estarão disponíveis em seus sub-objetos. A API de criar um Produto ficaria legal porque os clientes só precisam passar os IDs dos rolos para criar, e o backend saberia toda a informação.
O banco de dados ficaria assim. Note a join table entre Produtos e Rolos tb_products_in_stock_rolls
:
create table roll_model (
article_article_code uuid, -- FK
roll_number uuid not null, -- PK
primary key (roll_number)
)
create table tb_article_model (
article_code uuid not null, -- PK
cor_color_code uuid, -- FK
primary key (article_code)
)
create table tb_color (
color_code uuid not null, -- PK
color_name varchar(255),
primary key (color_code)
)
create table tb_products_in_stock (
cost_price float(53) not null,
size float(53) not null,
weigth float(53) not null,
id uuid not null, -- PK
invoice_date varchar(255),
invoice_number varchar(255),
order_number varchar(255),
treatment varchar(255),
primary key (id)
)
create table tb_products_in_stock_rolls (
product_model_id uuid not null, -- FK
rolls_roll_number uuid not null unique, -- FK
primary key (product_model_id, rolls_roll_number)
)
alter table if exists roll_model
add constraint FKc2fgr7j79edmcolp0elfhqit3
foreign key (article_article_code)
references tb_article_model
alter table if exists tb_article_model
add constraint FK11ojre7jnbvyxaq9hu7vixgsw
foreign key (cor_color_code)
references tb_color
alter table if exists tb_products_in_stock_rolls
add constraint FKf7gu54rqt0rwt5977edwy74kb
foreign key (rolls_roll_number)
references roll_model
alter table if exists tb_products_in_stock_rolls
add constraint FKfovrka47vy4b05wxsi191q07h
foreign key (product_model_id)
references tb_products_in_stock
Aqui um teste para exemplificar:
@Test
void createProduct() {
// 1. Criar uma Cor
var color = new ColorModel();
color.setColorCode(UUID.randomUUID());
color.setColorName("Pantone Mango Tango");
colorRepository.save(color);
// 2. Criar um Artigo contendo sua respectiva Cor
var article = new ArticleModel();
article.setArticleCode(UUID.randomUUID());
article.setArticleName("Soft cotton");
article.setCor(color);
articleRepository.save(article);
// 3. Criar varios Rolos contendo seus respectivos Artigo
var roll = new RollModel();
roll.setRollNumber(UUID.randomUUID());
roll.setArticle(article);
rollRepository.save(roll);
// 4. Criar um Produto contendo seus respectives Rolos
var product = new ProductModel();
product.setId(UUID.randomUUID());
product.getRolls().add(roll);
productRepository.save(product);
}
Aqui um pull request para demonstrar: https://github.com/tadeupinheiro/api-stock-input-spring-boot/pull/1
Bom, se entendi direito os requisitos, esta seria a minha sugestao.