Migrating Spring Boot application to Quarkus using JPA and JPA - spring-boot

Good afternoon, I'm new to Quarkus and I'm migrating a Spring Boot application, specifically a microservice that performs a DB query through a Procedure, to Quarkus using JPARepository, however I'm getting the following error:
Caused by: io.quarkus.spring.data.deployment.UnableToParseMethodException: Method 'findDataxMovil' of repository 'com.tmve.subscriber.repositories.FindAccountNumberRepository' cannot b
e parsed as there is no proper 'By' clause in the name.
My Repository and Entity classes are defined as follows, just like in Spring Boot:
AccountNumber
package com.tmve.subscriber.entities;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(name = "buscar_datos_x_movil", procedureName = "PERS.PKG_LCL_CUENTA.BUSCAR_DATOS_X_MOVIL", resultClasses = AccountNumber.class, parameters = {
#StoredProcedureParameter(mode = ParameterMode.IN, name = "p_movil", type = String.class),
#StoredProcedureParameter(mode = ParameterMode.IN, name = "p_fecha_operacion", type = Date.class),
#StoredProcedureParameter(mode = ParameterMode.REF_CURSOR, name = "p_lista", type = AccountNumber.class) }) })
#Setter
#Getter
#Entity
public class AccountNumber implements Serializable {
private static final long serialVersionUID= 1L;
#Id
private long id;
#Column (name= "NOMBRE")
private String nombre;
#Column(name="APELLIDO")
private String apellido;
#Column(name ="SE")
private String se;
#Column(name = "NUMERO_DOC_PRINCIPAL")
private String numeroDocPrincipal;
#Column(name = "ID_TIPO_DOCUMENTO")
private String idTipoDocumento;
#Column(name = "TIPO")
private String tipo;
#Column(name = "FECHA_NAC")
private String fechaNac;
#Column(name = "ID_CICLO_CONTROL")
private String idCicloControl;
#Column(name = "ID_MARCA")
private String idMarca;
#Column(name = "ID_MODELO")
private String idModelo;
#Column(name = "NOMBRE_MARCA")
private String nombreMarca;
#Column(name = "NOMBRE_MODELO")
private String nombreModelo;
#Column(name = "ESN")
private String esn;
#Column(name = "NUMERO_MOVIL")
private String numeroMovil;
#Column(name = "ID_CUENTA_PAGADORA")
private String idCuentaPagadora;
#Column(name = "ID_CUENTA_USO")
private String idCuentaUso;
}
FindAccountNumberRepository
package com.tmve.subscriber.repositories;
import com.tmve.subscriber.entities.AccountNumber;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.query.Procedure;
import org.springframework.data.repository.query.Param;
import java.sql.Date;
import java.sql.ResultSet;
public interface FindAccountNumberRepository extends JpaRepository<AccountNumber,String> {
#Procedure(name = "buscar_datos_x_movil")
ResultSet findDataxMovil(#Param("p_movil") String movil, #Param("p_fecha_operacion") Date fechaOperacion);
}
Application.Properties
quarkus.datasource.username=APP_MS_PERS_DEV
quarkus.datasource.password=xxxxxxxx
quarkus.datasource.jdbc.driver=oracle.jdbc.driver.OracleDriver
quarkus.datasource.jdbc.url=jdbc:oracle:thin:#1xxxxxxxxx:1531/PERSDES
quarkus.hibernate-orm.log.sql=true
That could be happening? It seems that it is taking the procedure as a Query from the fields of the Entity
Is there another method that could be applied?

Related

Config ModelMapper giving me an error when converting From a Set<Author> to Set<Integer>

I am trying to convert a book class (livro) to a bookDto. I was tryied doing that creating a bean config of model mapper but it is not working.
I have on the book class a Set of Authors (autores) and a Set of Genre (generos) and all classes have Integers ids. I want the BookDTO to have only a set of the ids. I guess the problem is on the model mapper config i did
package br.com.newgo.biblioteca.config;
import br.com.newgo.biblioteca.data.dto.output.LivroCriadoDto;
import br.com.newgo.biblioteca.data.entity.Autor;
import br.com.newgo.biblioteca.data.entity.Genero;
import br.com.newgo.biblioteca.data.entity.Livro;
import org.modelmapper.Converter;
import org.modelmapper.ModelMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Set;
import java.util.stream.Collectors;
#Configuration
public class MapperConfig {
#Bean
public ModelMapper modelMapper(){
ModelMapper modelMapper = new ModelMapper();
Converter<Set<Autor>, Set<Integer>> autoresParaAutoresId = context -> {
if (context.getSource() == null) {
return null;
}
return context.getSource().stream()
.map(Autor::getId).collect(Collectors.toSet());
};
Converter<Set<Genero>, Set<Integer>> generosParaGenerosId = context -> {
if (context.getSource() == null){
return null;
}
return context.getSource().stream()
.map(Genero::getId).collect(Collectors.toSet());
};
modelMapper.typeMap(Livro.class , LivroCriadoDto.class).addMappings(
src -> {
src.using(autoresParaAutoresId).map(Livro::getAutores, LivroCriadoDto::setAutores);
src.using(generosParaGenerosId).map(Livro::getGeneros, LivroCriadoDto::setGeneros);
});
return modelMapper;
}
}
Here is my book class:
package br.com.newgo.biblioteca.data.entity;
import jakarta.persistence.*;
import lombok.*;
import java.util.HashSet;
import java.util.Set;
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Entity()
#Table(name = "livros")
public class Livro {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(nullable = false)
private String nome;
#Column(nullable = false, length = 13)
private String isbn;
//de 10 ou 13?
#Column(nullable = false)
private Float valor;
#Column(nullable = false)
private Integer paginas;
#Column(nullable = false)
private Float altura;
#Column(nullable = false)
private Float largura;
#Column(nullable = false)
private Float profundidade;
#ManyToMany
#JoinTable(name = "livro_genero")
private Set<Genero> generos = new HashSet<>();
#ManyToMany
#JoinTable(name = "livro_autor",
joinColumns = #JoinColumn(name = "livro_id"),
inverseJoinColumns = #JoinColumn(name = "autor_id"))
private Set<Autor> autores = new HashSet<>();
}
and here is the dto i am trying to convert to :
package br.com.newgo.biblioteca.data.dto.output;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;
import java.util.HashSet;
import java.util.Set;
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class LivroCriadoDto {
#NotNull
private Integer id;
#NotBlank
private String nome;
#NotBlank
#Length(min = 10, max = 13)
private String isbn;
#NotNull
#Positive
private Float valor;
#NotNull
#Positive
private Integer paginas;
#NotNull
#Positive
private Float altura;
#NotNull
#Positive
private Float largura;
#NotNull
#Positive
private Float profundidade;
#NotNull
#NotEmpty
private Set<Integer> generos = new HashSet<>();
#NotNull
#NotEmpty
private Set<Integer> autores = new HashSet<>();
}
I am trying doing this
modelMapper.map(livro, LivroCriadoDto.class);
and it is returning me
Converter br.com.newgo.biblioteca.config.MapperConfig$$Lambda$1243/0x000000080140e3d8#16a95f37 failed to convert org.hibernate.collection.spi.PersistentSet to java.util.Set.
1) Converter br.com.newgo.biblioteca.config.MapperConfig$$Lambda$1243/0x000000080140e3d8#16a95f37 failed to convert org.hibernate.collection.spi.PersistentSet to java.util.Set.
Caused by: java.lang.NullPointerException
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at br.com.newgo.biblioteca.config.MapperConfig.lambda$modelMapper$0(MapperConfig.java:27)
at org.modelmapper.internal.MappingEngineImpl.convert(MappingEngineImpl.java:306)
at org.modelmapper.internal.MappingEngineImpl.setDestinationValue(MappingEngineImpl.java:243)
at org.modelmapper.internal.MappingEngineImpl.propertyMap(MappingEngineImpl.java:187)
at org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:151)
at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:105)
at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:71)
at org.modelmapper.ModelMapper.mapInternal(ModelMapper.java:589)
at org.modelmapper.ModelMapper.map(ModelMapper.java:422)
at br.com.newgo.biblioteca.domain.services.LivroService.cadastrar(LivroService.java:51)
at br.com.newgo.biblioteca.presentation.controllers.LivroController.cadastrar(LivroController.java:21)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1010)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:913)
The problem was that jpa was creating a Autor and Genero null because it was not supposed to be null and passing it no Livro

How to add the IDs of foreign tables to another table passing the parameters by constructor?

Hi everyone I'm working with SpringBoot and I want to send the ID's of table Producto and Cliente to Pedidos, I'm using the constructor for to pass of parametrs
I tried to create a List as String to hold the values ​​and then use it to send the data to the other method
Class Product
package com.example.demo.model;
import java.util.Set;
import javax.persistence.*;
#Entity
#Table(name = "Productos")
public class Producto {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nombreProducto;
private String precioProducto;
/*Here i send of FK of this table to Pedidos*/
#OneToMany(mappedBy = "producto",cascade = CascadeType.ALL)
private Set<Pedido> pedidos;
public Producto(String nombreProducto, String precioProducto) {
this.nombreProducto = nombreProducto;
this.precioProducto = precioProducto;
}
//Getters and Setters
}
Class Cliente
package com.example.demo.model;
import java.util.Set;
import javax.persistence.*;
#Entity
#Table(name="Clientes")
public class Cliente {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nombreCliente;
private String correoElectronico;
/*Here i send of FK of this table to Pedidos*/
#OneToMany(mappedBy = "cliente",cascade = CascadeType.ALL)
private Set<Pedido> pedidos;
public Cliente(String nombreCliente, String correoElectronico) {
this.nombreCliente = nombreCliente;
this.correoElectronico = correoElectronico;
}
//Getters and Setters
}
Class Pedido
package com.example.demo.model;
import javax.persistence.*;
#Entity
#Table(name = "Pedido")
public class Pedido {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String fechaPedido;
private String direccion;
/*
Here I create the atribute of FK of the tables Cliente and Producto
*/
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "cliente_id", referencedColumnName = "id")
private Cliente cliente;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "producto_id", referencedColumnName = "id")
private Producto producto;
public Pedido(String fechaPedido, String direccion, Cliente cliente, Producto producto) {
this.fechaPedido = fechaPedido;
this.direccion = direccion;
this.cliente = cliente;
this.producto = producto;
}
//Getters and Setters
}
And the last Class it's the RunnClass
package com.example.demo;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
//import java.util.stream.Stream;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import com.example.demo.model.Cliente;
import com.example.demo.model.Pedido;
import com.example.demo.model.Producto;
import com.example.demo.repository.ClienteRepository;
import com.example.demo.repository.PedidosRepository;
import com.example.demo.repository.ProductoRepositroy;
import com.github.javafaker.Faker;
#Component
public class SampleDataLoader implements CommandLineRunner {
private final ClienteRepository clienteRepository;
private final ProductoRepositroy productoRepositroy;
private final PedidosRepository pedidosRepository;
private final Faker faker; //It's a ASI of DataFaker
public SampleDataLoader(ClienteRepository clienteRepository,
ProductoRepositroy productoRepositroy,
PedidosRepository pedioPedidosRepository) {
this.clienteRepository = clienteRepository;
this.productoRepositroy = productoRepositroy;
this.pedidosRepository = pedioPedidosRepository;
this.faker = new Faker(); //It's a ASI of DataFaker
}
#Override
public void run(String... args) throws Exception {
ejecutarClases();
}
private void ejecutarClases() {
List<Cliente> clientes = IntStream.rangeClosed(1, 20)
.mapToObj(i -> new Cliente(faker.name().fullName(),
faker.internet().emailAddress()))
.collect(Collectors.toList());
clienteRepository.saveAll(clientes);
List<Producto> productos = IntStream.rangeClosed(1, 100)
.mapToObj(i -> new Producto(faker.commerce().productName(), "$"+faker.commerce().price()))
.collect(Collectors.toList());
productoRepositroy.saveAll(productos);
//I don't know how to send two ID's to this table,
//if you can see I have two values as null
//I want to send the ID's the other tables
List<Pedido> pedidos = IntStream.rangeClosed(1, 30)
.mapToObj(i -> new Pedido(faker.backToTheFuture().date(),
faker.address().streetAddress(), null, null))
.collect(Collectors.toList());
pedidosRepository.saveAll(pedidos);
}
}
I hope someone can help me please.

REST API Infinite loop

My API shows me infinite loop for adress field
When I insert #JsonIgnore, #JsonManagedReference or #JsonBackReference
I can clearly see one result as it should be, but than i don't have nested address fields.
What should I do to have also that address fields but one result?
These are my main entities:
1.Property
package com.realestate.petfriendly.entity;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Data;
#Entity
#Data
#Table(name = "property")
public class Property {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_property")
private int id_property;
#Column(name = "title")
private String title;
#Column(name = "type")
private String type;
#Column(name = "room")
private String room;
#Column(name = "price")
private double price;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "address_id_address")
// #JsonBackReference
private Address address;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "user_id_user")
// #JsonBackReference
private User user;
}
User
package com.realestate.petfriendly.entity;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
#Entity
#Getter
#Setter
#Table(name = "user")
class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_user")
private int id_user;
#Column(name = "username")
private String username;
#Column(name = "name")
private String name;
#Column(name = "lastname")
private String lastname;
#Column(name = "phone")
private String phone;
#Column(name = "notes")
private String notes;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "user_address_id_user_address")
// #JsonManagedReference
private UserAddress userAddress;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user")
// #JsonManagedReference
private List<Property> property = new ArrayList<>();
}
Address
package com.realestate.petfriendly.entity;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
#Entity
#Getter
#Setter
#Table(name="address")
class Address{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_address")
private int id_address;
#Column(name = "city")
private String city;
#Column(name = "municipality")
private String municipality;
#Column(name = "place")
private String place;
#Column(name = "street")
private String street;
#Column(name = "house_number")
private double house_number;
#OneToOne(mappedBy = "address")
// #JsonManagedReference
private Property property;
}
You actually have the solution to your problem in your code, but the key annotations are commented-out and in the wrong places (according to your requirements). One of the ways to tackle this is by using #JsonManagedReference and #JsonBackReference as follows:
#Entity
#Data
#Table(name = "property")
public class Property {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_property")
private int id_property;
#Column(name = "title")
private String title;
#Column(name = "type")
private String type;
#Column(name = "room")
private String room;
#Column(name = "price")
private double price;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "address_id_address")
#JsonManagedReference
private Address address;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "user_id_user")
#JsonBackReference
private User user;
}
#Entity
#Getter
#Setter
#Table(name = "user")
class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_user")
private int id_user;
#Column(name = "username")
private String username;
#Column(name = "name")
private String name;
#Column(name = "lastname")
private String lastname;
#Column(name = "phone")
private String phone;
#Column(name = "notes")
private String notes;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "user_address_id_user_address")
private UserAddress userAddress;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user")
#JsonManagedReference
private List<Property> property = new ArrayList<>();
}
#Entity
#Getter
#Setter
#Table(name="address")
class Address{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_address")
private int id_address;
#Column(name = "city")
private String city;
#Column(name = "municipality")
private String municipality;
#Column(name = "place")
private String place;
#Column(name = "street")
private String street;
#Column(name = "house_number")
private double house_number;
#OneToOne(mappedBy = "address")
#JsonBackReference
private Property property;
}
Keep in mind the following:
#JsonManagedReference is the forward part of the relationship: the one that gets serialized normally.
#JsonBackReference is the back part of the relationship: it will be omitted from serialization.
If you want to have a reference to the back part of the relationship, you can use #JsonIdentityInfo as follows:
#Entity
#Data
#Table(name = "property")
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id_property")
public class Property {
(...)
}
#Entity
#Getter
#Setter
#Table(name = "user")
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id_user")
class User {
(...)
}
#Entity
#Getter
#Setter
#Table(name="address")
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id_address")
class Address{
(...)
}
You can read more about these and other techniques in the following online resource: https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion.
You have circular dependency between Property and Address class. In order to block infinite JSON serialization loop you can add #JsonIgnore annotation on one side of related properties

No property .. found for type .. in spring boot

I'm a beginner with spring and I have this little issue. "No property questionId found for type CourseTestCompleteField!" I have 2 model classes that are connected via a one to one join.
That 2 model class are:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "questions")
public class CourseTestQuestion {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="question_id")
private Long id;
#NotBlank
#Column(name = "question_course")
private String questionCourse;
#NotBlank
#Column(name = "question_type")
private String questionType;
public CourseTestQuestion(){
}
public CourseTestQuestion(String questionCourse, String questionType) {
this.questionCourse = questionCourse;
this.questionType = questionType;
}
// public getters and setters for all fields here
}
And:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "quiz_complete_field_questions",
uniqueConstraints = {
#UniqueConstraint(columnNames = "question_id")
}
)
public class CourseTestCompleteField {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Column(name = "question_content")
private String questionContent;
#NotBlank
#Column(name = "answer")
private String answer;
#NotBlank
#Column(name = "points")
private String points;
#NotBlank
#Column(name = "course")
private String course;
#NotBlank
#Column(name = "teacher_username")
private String teacher;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "question_id", referencedColumnName = "question_id")
private CourseTestQuestion courseTestQuestion;
public CourseTestCompleteField(){
}
public CourseTestCompleteField(CourseTestQuestion courseTestQuestion, String question, String answer, String points, String course, String teacher) {
this.courseTestQuestion = courseTestQuestion;
this.questionContent = question;
this.answer = answer;
this.points = points;
this.course = course;
this.teacher = teacher;
}
// public getters and setters for all fields here
}
My repo for both:
package com.example.springboot.repository;
import com.example.springboot.models.Course;
import com.example.springboot.models.CourseTestQuestion;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface CourseTestQuestionRepository extends JpaRepository<CourseTestQuestion, Long> {
Optional<CourseTestQuestion> findById(Long id);
Optional<CourseTestQuestion> findByQuestionCourse(String questionCourse);
}
And:
package com.example.springboot.repository;
import com.example.springboot.models.CourseTestCompleteField;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
#Repository
public interface CourseTestCompleteFieldRepository extends JpaRepository<CourseTestCompleteField, Long> {
Optional<CourseTestCompleteField> findById(Long id);
Optional<CourseTestCompleteField> findByQuestionId(Long questionId);
Optional<CourseTestCompleteField> findByCourse(String course);
List<CourseTestCompleteField> findByQuestionContent(String questionContent);
List<CourseTestCompleteField> findByTeacher(String teacher);
Boolean existsByQuestionContent(String questionContent);
}
The problem is with Optional<CourseTestCompleteField> findByQuestionId(Long questionId);but I don't get it why, because in database I have the table for CourseTestCompleteFieldModel with question_id column, and in CourseTestCompleteField I have CourseTestQuestion object. Tho, the table for CourseTestCompleteField has a different name, could be this a problem? I should rename the table to course_test_complete_field?
Can someone help me please? Thank you
Since,This is a query on nested Object. You need to update your query as this.
Optional<CourseTestCompleteField> findByCourseTestQuestion_Id(Long questionId);
This works even without "_"
Optional<CourseTestCompleteField> findByCourseTestQuestionId(Long questionId);
But better to put "_" while accessing nested fields for better readability.
There is no field call questionId in you entity and you have id only.
That's you got error. You can use that findyById(). That's only enough.
If you would like write JPA repository method like findBy..., getBy..., deleteBy...., countBy..., After this you need append exact field name from entity.
For example if you entity have name then can write below methods. findByName(); deleteByName(); countByName();
So try as below.
findBycourseTestQuestion(Object o);
Pass questions object.

JPA/Hibernate. How to get child objects contained in a list of Parent object using createQuery method

I have Certificate class that contains list of Tag classes
import javax.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
#Entity
#Table(name = "gift_certificate")
public class Certificate {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private BigDecimal price;
private Integer duration;
#Column(name = "create_date")
private LocalDateTime createDate;
#Column(name = "last_update_date")
private LocalDateTime lastUpdateDate;
#ManyToMany
#JoinTable(name = "gift_certificate_tag",
joinColumns = #JoinColumn(name = "tag_id"),
inverseJoinColumns = #JoinColumn(name = "gift_certificate_id")
)
private List<Tag> tags;
getters and setters and other code...
....
import javax.persistence.*;
import java.util.Objects;
#Entity
#Table(name = "tag")
public class Tag {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
getters and setters and other code...
And I'm trying to get List of Certificate from DB using JPA/Hibernate.
I'm using EntityManager
public List<Tag> getCertificateTags(Long certificateId) {
return entityManager.createQuery("select c.tags from Certificate c where c.id=:id")
.setParameter("id", certificateId)
.getResultList();
}
And it works, but I get just list, not List and IDEA is warning Unchecked assignment: 'java.util.List' to 'java.util.List<Tag>'.
And when I use createQuery with second parameter Tag.class like this:
entityManager.createQuery("select c.tags from Certificate c where c.id=:id", Tag.class)
.setParameter("id", certificateId)
.getResultList();
I get java.lang.IllegalArgumentException: Type specified for TypedQuery [Tag] is incompatible with query return type [interface java.util.Collection]
How can I fix it?
Try to change the query this way
select t from Certificate c join c.tags t where c.id=:id
The reason is that select c.tags means every result row contains a list of tags. But when you select t from Certificate c join c.tags t every row contains one tag

Resources