JPA não cria o aluno por causa do List<>, mesmo eu pedindo a criação de uma tabel ManyToMany

não entendo o porque dele está sendo impedido de criar a tabela, ele declara isso ai como null
fora que eu não consigo criar um Aluno com a List vazia.

esta faltando informações do erro. aparentemente o erro nao é no relacionamento das entidades. o erro esta no Controller. cole aqui o erro completo do console.

@PostMapping
	public ResponseEntity<?> CriaAluno(){
		
		
		Aluno alysson= new Aluno("nome" ,"senha", "email");
	
		crud.buscaLivro(1l).forEach(u->{alysson.getLivros_lidos().add(u);
		
		System.out.println(u.getId());
		});
		
		crud.atualizar(alysson);
		
		return new ResponseEntity<>(HttpStatus.OK);
		
	}

na vdd acho que já resolvi, plmns parcialmente. Eu precisava criar o Aluno antes de popular a tabela relacional entre alunos e livros_lidos.

Antes de chegar nesse ponto, estava dando um erro que eu não poderia criar um aluno sem declarar uma FK que relacione ele à aos livros, isso acontecia pq eu tava mandando o JoinTable pra tabela aluno, criando uma coluna que não dava pra ser preenchida. AI eu resolvi isso fznd o jpa criar uma tabela relacional @JoinTable(name=“livros lidos” etc…).
com isso resolvido, veio um erro que ele não conseguia criar alunos com lista de livros(esse que mostrei, que tava retonando só null), isso pq eu primeiro precisava criar o objeto aluno, pra depois relacionar ele com a tabela livros_lidos.

é o seguinte, quando voce usa um array, e voce faz esse metodo ai para percorrer ele, quando o Aluno é criado, o array nao esta inicializado. Por isso voce recebe esse erro.

Para resolver, voce precisa criar um construtor vazio em aluno, e initializar o array

public Aluno() {
   livros_lidos = new ArrayList<>();
}

vi que voce tem um construtor com parametros, entao voce inicia o array la tambem.

1 curtida

Exatamente isso, mas o JPA já faz isso pra mim, se o aluno já existir. então eu preciso primeiro criar o aluno e depois adicionar, justamente por isso ai que vc falou, a array ainda não existe.
Esse erro eu resolvi criando o aluno primeiro, e adicionando os livros na lista depois. Esse foreach() busca a lista na tabela do banco de dados pra adicionar na lista de livros lidos.

O que o @thimor disse eh que o erro aconteceu por conta da lista livros_lidos está nula.

eu entendi, o erro já foi resolvido, oq eu to falando é que o JPA já instancia essa lista pra mim quando eu busco o Objeto Aluno da tabela, Essa list, faz referência à uma tabela relacional, unidirecional nxn, que o JPA cria pela tag @ManyToMany. O problema real era que eu não podia criar uma referencia a essa tabela de livros lidos, se o objeto aluno não existe, logo o JPA não pode instanciar essa lista, ai quando vc tenta criar o objeto aluno aluno e adicionar um livro lido antes do flush ele da null. Mas acho que se eu criasse a a instância da list como o @thimor, tbm resolveria, mas ai eu seria obrigado à por uma list toda vez que fosse criar um aluno.

nao precisa por uma list, a falta do array inicializado, é o motivo pelo qual voce relatou que nao consegue criar um aluno sem uma lista de livros. Pois quando voce cria um aluno e vai percorrer o forEach que voces fez da o erro. Nao precisava ter alterado nada no codigo que voce ja tinha feito, apenas instanciar um array vazio nos construtores da classe aluno.

o erro não era no foreach, esse foreach percorre uma lista já existente, a de livros que é o resultado de uma TypedQuery.getResultList(). O problema era msm que o Aluno, como uma Entity, não pode ser criado com atributos que não existam na tabela do MySQL. Logo eu não posso criar um aluno, ai dps, aluno.getLivros_Lidos.add(Livro), pra só então mandar esse aluno pra Tabela. Na vdd eu n precisei mudar nada no código, só não adicionei o livro na lista. Mas oq vc falou ta certo tbm, se eu instanciasse essa lista td vez que o construtor aluno fosse chamado, ele não iria acusar o nullpointer, mas optei por n fzr pra poupar um campo no JSON.

é justamente isso que voce nao entendeu. voce nao consegue fazer

aluno.getLivros_lidos().add(livro)

por que voce nao inicializou o array de livros lidos em nenhum construtor de aluno. É isso que eu estou lhe falando e voce ainda nao conseguiu entender.

Se voce tiver um construtor vazio ou um com parametros que tenha livros lidos = new arraylist() isso que voce esta dizendo que nao funciona pq acha que é da jpa, ira funcionar sim

então é justamente isso que eu to falando que era oq tava dando problema. por isso eu faço persist(aluno) em um método, ai quando eu quiser adicionar um livro na lista de livros lidos eu vou lá e faço um merge(aluno) em outro método.

Não, eu disse que funciona, seu método funciona, se fosse o caso por exemple de eu estar utilizando JDBC puro, essa seria a unica solução, mas como eu estou usando JPA, ele já faz essa relação pra mim, instancia uma List que representa a tabela relacional Livros_lidos, ai eu optei por não declarar essa lista no construtor, pra diminuir o JSON

isso que voce esta fazendo é totalmente desnecessario. Porque a JPA trabalha com cascade. voce cria um objeto coloca todos relacionamentos dele, pode ser os que for, e no final chama apenas o persist. nao precisa fazer persist, depois recuperar para adicionar e fazer um merge.

nao tem nada a ver com jpa ou jdbc puro. é simplesmente OO ainda aqui. voce esta construindo um objeto para depois ele ir para o ORM de persistencia.

Não, não é isso que eu quis dizer. a aplicação funciona da seguinte forma, vc cria um aluno com os parâmetros nome, email, senha; ai vc tem acesso à aplicação, essa alicação permite vc alugar livros, quando vc aluga um livro e devolve, o livro entra pra lista livros_lidos, logo não há sentido eu obrigar meu cliente a preencher uma lista de livros consumidos, se ele nem mesmo teve acesso à biblioteca, por tanto não há pq eu declarar a lista no campo já que essa lista já é instanciada automaticamente sempre que eu chamar o objeto Aluno da tabela. Eu não alterei nada, não criei nenhum método a mais pra resolver esse problema, eu só segui as regras de negócio da aplicação. Então eu não fiz nada desnecessário, justamente pq só deixei de fzr.