Olá,
Tenho uma dúvida sobre orientação a objetos na prática, principalmente com interface.
Por exemplo,
Suponha que eu tenha o seguinte cenário.
public abstract class Funcionario {
private Double salario;
public abstract void calculaBonificacao();
public Double getSalario() {
return salario;
}
public void setSalario(Double salario) {
this.salario = salario;
}
}
class Gerente extends Funcionario{
@Override
public void calculaBonificacao() {
// implementacao
}
}
class Vendedor extends Funcionario{
@Override
public void calculaBonificacao() {
// implementacao
}
}
Neste caso o que eu teria ?
class FuncionarioBO {
private FuncionarioRepository repository;
public void calcularSalario(Funcionario funcionario){
funcionario.calculaBonificacao();
repository.salvar(funcionario);
}
}
Mas na prática a arquitetura mais comum é as regras de negócio ficarem centralizadas no Objeto de negócio. Neste exemplo dei não vejo como poderia salvar o estado do objeto já que acredito que o Hibernate não entenderia isso e daria erro, correto ?
Uma outra situação seria um outro método que recebe alguém que implementa uma interface e tem que salvar esse objeto de forma polimórfica.
Alguém sabe tirar essas dúvidas minhas ? Tenho muito mais dúvidas relacionadas ao assunto, mas a explicação disso já me daria um norte.
Alguém ?
apenas uma correção vc não criou uma interface, vc criou uma classe abstrata, para criar interface é assim:
public interface Funcionario {
}
agora um artigo q vc pode estar lendo pra entender melhor é:
https://www.devmedia.com.br/interfaces-x-classes-abstratas/13337
Desculpe, mas talvez o nome do tópico tenha te levado a interpretar errado a pergunta. Mudei para "programação orientada a abstração " . Neste exemplo funcionário é uma classe abstrata, mas a minha dúvida é sobre salvar o estado de objeto objetos abstratos ou interfaces .
O hibernate “olha” para o objeto e o compara ao mapeamento disposto.
Ao “olhar” o objeto, o mecanismo do hibernate identifica o que pode ou não ser persistido (transient, por exemplo), valida se o mesmo está no grupo de entidades mapeadas (em um arquivo .hbm.xml ou anotado como @Entity) e faz a validação com a tabela específica (pelo nome da classe ou pela anotação @Table), verifica as colunas, PK, FK, uniques, constraints e etc e, só então, permite que você realize operações (como insert, update, etc).
Logo, o que conta, para o hibernate, é como o mapeamento está e como o objeto é aderente a ele.
1 curtida
Então você está dizendo que se a instância que for passada para a classe Funcionario for instancia de Gerente o Hibernate consiguira persistir perfeitamente porque ele vai buscar se a instancia desse objeto esta mapeada ? Ou seja, se eu chamar funcionarioBO.calcularSalrio(new Gerente()); o hibernate conseguira persistir o objeto na Tabela correta se Gerente estiver mapeado corretamente ?
Mas como isso seria se por exemplo :
interface Historico{}
@Entity
class HistoricoA implements Historico{}
@Entity
class HistoricoB implements Historico{}
class HistoricoBO {
HistoricoRepository repository;
public void manipulaEGravaEstado(Historico historico){
//historico.alguma coisa aqui
repository.salvar(historico);
}
}
Um método no BO que recebe alguém que implementa determinada interface, executa alguma operação e então grava o estado do objeto na tabela correta.
Entendeu ?
Depende de qual foi a forma que você mapeou e qual estratégia está utilizando para a herança (single table ou não).
Mas, teoricamente, sim, o hibernate vai olhar o mapeamento, vai identificar o tipo do objeto e comparar com o que foi definido no mapeamento,
Basicamente, é isso.
Aqui temos duas coisas:
- Os atributos do objeto e seus respectivos valroes
- O estado do objeto
Creio que você esteja confundindo isso.
Quando falamos em ORM, como hibernate, não falamos em salvar o estado do objeto em si, isso seria responsabilidade de um mecanismo de serialização e o objeto deveria ser de uma classe que estende a interface Serializable.
A função específica do hibernate é pegar os atributos (na verdade, a referência de cada atributo e o valor dado a cada um deles) e, baseado no mapeamento definido, persistir, realizar select, update, insert e delete. Ele não usa o objeto como todo, mas, a parte mapeada do mesmo (e não transient)
Correto, mas nesse exemplo que lhe dei HistoricoRepository repository; Funcionaria corretamente e conseguiria salvar de forma dinâmica o objeto no banco de dados ?
Porque pelo menos nos Spring Data Jpa ao criar a seguinte classe :
public interface HitoricoRepository extends JpaRepository<Historico, Long> {}
Ocorre um erro dizendo que a Historico não está mapeado (e realmente não está, é uma interface). Ou seja, para resolver isso acredito que deva ter um HistoricoARepository e um HistoricoBRepository para suas respectivas classes. Ou seja, dessa maneira imagino o método historicoBo.manipulaEGravaEstado(new HistoricoA()); contendo uma implementação contendo um
if(historico instanceof HistoricoA){
historicoABO.salvar(historico);
}else if(historico instanceof HistoricoB){
historicoBBO.salvar(historico);
}
Quero evitar essa verificação algo mais ou menos nesse sentido.
public interface HitoricoRepository extends JpaRepository<Historico, Long> {}
Interfaces definem comportamentos comuns, não definem atributos comuns, logo, tentar persistir um elemento a partir da comparação de tipo com uma interface, não e´um caminho adequado a se seguir.
É cabível, porém, que você tenha algo como
@Entity
public class Foo implements Serializable {}
Por exemplo.
Agora, se você tem a intenção de ter um HistoricoA e HistoricoB, primeiro precisa ter certeza que precisa destas duas classes. Segundo, se ambos são históricos você pode criar uma classe, mesmo abstrata, Historico e fazer com que HistoricoA e HistoricoB estendam desta classe.
@MappedSuperclass
public abstract class Historico {}
@Entity
public HistoricoA extends Historico{}
@Entity
public HistoricoB extends Historico{}
Aí faz sentido, pelo menos, para mim.
Suponha que Historico/Relatorio seja uma interface define um comportamento em comum, e a regra fosse essa ou algo parecido com isso. O histórico foi um exemplo. Se esse cenário que fosse exposto fosse um cenário real, como seria ? Seria da maneira como expus mesmo ?
@MappedSuperclass public abstract class ClasseQualquer{}
O que você precisa observar, antes de qualquer coisa, é que um framework, seja qual for, é desenvolvido com o objetivo de atender ao que existe de mais corriqueiro.
Sendo assim, o hibernate pode não atender a todas as situações que existem ou que você venha a encontrar.
Volto a tecla que: apenas se o objeto vier de uma classe mapeada é que ele será persistido pelo hibernate. Qualquer coisa fora disso, não funciona.
Como não é possível mapear interfaces, logo, você nunca conseguirá tratar um cenário em que o objeto a ser persistido “é um” elemento daquela interface. Lógico, isso de acordo com o que eu conheço. Pode haver alguma maneira, mas, eu desconheço.
1 curtida