Mapeamento JPA:Hibernates - could not instantiate test object

Olá,

Estou criando um projeto de um Banco Digital, nele há a seguinte hierarquia de classes:

ContaCorrente extends Conta
CartaoDebito extends Cartao

Além disso,

  • CartaoDebito é um atributo de ContaCorrente ;
  • CartaoDebito tem como atributo uma Conta;

Estou com dificuldade de firmar esse relacionamento dentro de um banco de dados utilizando Hibernates.

Seguem as classes e a exception que está dando:

CONTA

@Entity
@SequenceGenerator(name = "numero_da_conta_seq", sequenceName ="numero_da_conta_seq", initialValue = 1000000000 , allocationSize = 1)
@Inheritance(strategy =InheritanceType.SINGLE_TABLE)
public abstract class Conta {
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "numero_da_conta_seq")
	@Id
	private Long numeroDaConta;
	private String agencia = "0001";
	@Enumerated(EnumType.STRING)
	private EnumConta tipoDeConta;
	@ManyToOne
	private Cliente cliente;
	public BigDecimal saldo = new BigDecimal("0");
	private String senha;
	@OneToOne(mappedBy = "contaMae", cascade = CascadeType.ALL) 
	protected ExtratoBancario extrato= new ExtratoBancario(this);

CONTA CORRENTE

@Entity
public class ContaCorrente extends Conta implements RentavelOuTributavel, GerenciavelPeloSistema {
	protected LocalDate ultimaCobranca = LocalDate.of(2023, 1, 1);
	@OneToOne(mappedBy = "contaAssociada")
	private CartaoCredito cartaoDeCredito;
	@OneToOne(mappedBy = "contaAssociada")
	@JoinColumn(name = "contaAssociada_numeroDaConta")
	private CartaoDebito cartaoDeDebito;

CARTÃO

@Entity
@SequenceGenerator(name = "numero_do_cartao_seq", sequenceName ="numero_do_cartao_seq", initialValue = 1000000000*100 , allocationSize = 1)
@Inheritance(strategy =InheritanceType.SINGLE_TABLE)
public abstract class Cartao {
	@OneToOne
	protected Conta contaAssociada;
	@Enumerated(EnumType.STRING)
	protected EnumCartao tipoDeCartao;
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "numero_do_cartao_seq")
	@Id
	private Long numero;
	private Integer senha;
	private boolean bloqueado;

CARTÃO DE DÉBITO

@Entity
public class CartaoDebito extends Cartao implements GerenciavelPeloSistema {
	private BigDecimal limiteDiario = contaAssociada.getCliente().getCategoria().getLimiteDiarioTransacaoDebito();
	private BigDecimal limiteDisponivel = limiteDiario;
	protected LocalDate ultimaRenovacaoLimiteDisponivel = LocalDate.of(2023, 1, 1);

EXCEPTION

Exception in thread "main" java.lang.ExceptionInInitializerError
	at com.fourcamp.bancoOGP.App.main(App.java:19) (NESTA LINHA HÁ A CRIAÇÃO DO ENTITY MANAGER)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: teste3] Unable to build Hibernate SessionFactory
Caused by: org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
Caused by: org.hibernate.InstantiationException: could not instantiate test object : com.fourcamp.bancoOGP.model.CartaoDebito
Caused by: java.lang.reflect.InvocationTargetException
Caused by: java.lang.NullPointerException
	at com.fourcamp.bancoOGP.model.CartaoDebito.<init>(CartaoDebito.java:28)
	... 25 more

O que tem nessa linha?

É a linha do primeiro atributo de CartaoDebito
@staroski

@Entity
public class CartaoDebito extends Cartao implements GerenciavelPeloSistema {
	private BigDecimal limiteDiario = contaAssociada.getCliente().getCategoria().getLimiteDiarioTransacaoDebito();   <----------- LINHA 28

E como é que contaAssociada foi inicializada?

@staroski

contaAssociada é a conta dona do cartão de débito, essa existe anteriormente à criação do cartão e entra como parâmetro no construtor do cartão através do método abaixo:

public void emitirCartaoDebito(Integer senhaDoCartao, String senhaDaConta) {
		try {
		checaSenha(senhaDaConta);
		
		CartaoDebito cartao = new CartaoDebito(this, senhaDoCartao);
		this.cartaoDeDebito = cartao;
		
		EntityManager em = JPAUtil.getEntityManager();
		ContaDAO dao = new ContaDAO(em);
		
		em.getTransaction().begin();
		dao.atualizar(this);
		em.getTransaction().commit();
		em.close();
		
		} catch(Exception e) {
			e.getCause();
		}
	}

Segue também o construtor do CartaoDebito:

protected CartaoDebito(Conta contaAssociada, Integer senha) {
		super(contaAssociada, senha);
		this.tipoDeCartao = EnumCartao.DEBITO;
		
		EntityManager em = JPAUtil.getEntityManager();
		CartaoDAO dao = new CartaoDAO(em);
		
		try {
		em.getTransaction().begin();;
		dao.cadastrar(this);
		em.getTransaction().commit();;
		em.close();
		} catch(Exception e) {
			e.getCause();
		}
	}

Segue o construtor de CARTAO (classe mãe):

protected Cartao(Conta contaAssociada, Integer senha) {
		this.contaAssociada = contaAssociada;
		this.senha = senha;
		this.bloqueado = true;
	}

Inicialize o atributo limiteDiario dentro do construtor de CartaoDebito pois ao tentar inicializar na declaração, o atributo contaAssociada ainda não foi inicializado.

Dê uma lida aqui para entender o processo de inicialização.

1 curtida

Amigo, muitíssimo obrigado!

Pode parecer bobo, mas você acaba de destravar algo que singificava muito para mim e que eu não achei orientação em lugar nenhum.

@staroski

1 curtida