Spring-Data-Jpa OneToMany query duplicate ids in the info log? - spring-boot

I don't understand why the ids are duplicated (id_msg, id_pers_acct), that's what's in my Springboot log :
select personneco0_.id_pers_acct as id_pers_1_2_0_,
…
from test.person_account personacc0_ where personacc0_.id_pers_acct=?
select messages0_.id_pers_acct as id_pers_5_1_0_,
messages0_.id_msg as id_msg1_1_0_,
messages0_.id_msg as id_msg1_1_1_,
messages0_.content as content2_1_1_,
messages0_.date as date3_1_1_,
messages0_.id_pers_acct_person_account as id_pers_4_1_1_,
messages0_.id_pers_acct as id_pers_5_1_1_
from test.message messages0_ where messages0_.id_pers_acct=?
In my entity PersonAccount i have this code :
#OneToMany(mappedBy = "sender", fetch = FetchType.LAZY)
public Set<Message> messages = new HashSet <Message>();
In my entity Message i have this code :
#Entity
#Table(name = "MESSAGE", catalog = "TEST")
public class Message implements Serializable{
/**
*
*/
private static final long serialVersionUID = -602563072975023074L;
#Id
#GeneratedValue
#Column(name = "ID_MSG")
Long idMsg;
#Column(name = "CONTENT")
String content;
#Column(name = "DATE")
Date date;
#Column(name = "ID_PERS_ACCT", nullable = false)
Long sender;
#Column(name = "ID_PERS_ACCT_PERSON_ACCOUNT", nullable = false)
Long receiver;
In my RestController, i call this :
#RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
public PersonAccount getUser(#PathVariable Long id) {
return userRepository.getOne(id);
}

Related

Sending file and JSON in a many-to-many relationship

I have a model called EPI that has a many to many relationship with Model Images, I am not able to do the #PostMapping for this object.
see my code
EPI Entity:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
#Table(name = "EPI")
public class EPI implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Id_EPI")
private UUID id;
#Column(name = "Nome", nullable = false, length = 100)
private String nome;
#Column(name = "Marca", nullable = false, length = 100)
private String marca;
#Column(name = "CA", nullable = false, length = 100)
private String ca;
#Column(name = "Descricao", nullable = false)
private String descricao;
#Column(name = "Foto")
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "epi_images",
joinColumns = {
#JoinColumn(name = "epi_id")
},
inverseJoinColumns = {
#JoinColumn(name = "image_id")
})
private Set<ImageModel> foto;
#Column(name = "Quantidade", nullable = false)
private Integer quantidade;
}
Image Entity:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
#Table(name = "image_model")
public class ImageModel implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
#Column(name = "type")
private String type;
#Column(name = "image_data", unique = false, nullable = false, length = 100000)
private byte[] imageData;
}
Controller EPI:
#PostMapping("/addNewEPI")
public ResponseEntity<Object> salvarFEPI(#RequestPart("image")MultipartFile file,
#RequestPart("epiModel") EPI epi) throws IOException {
try {
ImageModel foto = productImageService.uploadImage(file);
epi.setFoto((Set<ImageModel>) foto);
return ResponseEntity.status(HttpStatus.CREATED).body(epiService.save(epi));
} catch (Exception e){
System.out.println(e.getMessage());
return null;
}
Service Image:
public ImageModel uploadImage(MultipartFile file) throws IOException {
ImageModel image = new ImageModel();
image.setName(file.getOriginalFilename());
image.setType(file.getContentType());
image.setImageData(ImageUtility.compressImage(file.getBytes()));
return image;
}
As I am passing the parameters in Postman:
enter image description here
Return from Spring Boot:
enter image description here
If anyone can help me I would be very grateful!
I tried passing the parameters in different ways. I just want it to populate my tables passing the parameters of the EPI entity and the Image file.
enter image description here

Question on persisting entity with Bidirectional #ManyToOne relationship using Mapstruct

This is my first time implementing #ManyToOne relationship using JPA/Mapstruct/Spring boot. I am running into the below exception: (NOTE: Using generic names as I am unable to share all the details)
java.sql.SQLIntegrityConstraintViolationException: Column 'A_ID' cannot be null for class B when I try to persist A.
Below are the relevant details. Can you help me understand what is the mistake I am making here? I have spent few hours debugging this and reading the posts without success yet.
#Mapper(componentModel="spring", uses= {BMapper.class}, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface AMapper {
#Mapping(target = "aId", source="id")
#Mapping(target = "aName", source = "name")
ADTO toDTO(final A a);
#Mapping(target = "id", ignore=true)
#Mapping(target = "name", source = "aName")
A toEntity(final ADTO aDTO);
#AfterMapping
default void setBSet(A a, #MappingTarget aDTO dto) {
for(B b : a.getBs())
b.setA(a);
}
}
#Mapper(componentModel="spring", uses= {CMapper.class}, injectionStrategy = InjectionStrategy.CONSTRUCTOR )
public interface BMapper {
#Mapping(target = "bId", source="id")
#Mapping(target = "aName", ignore=true)
BDTO toDTO(final B b);
#Mapping(target = "id", ignore=true)
#Mapping(target = "a", ignore=true)
B toEntity(final BDTO bDTO);
Set<B> bDtoToBSetEntity(Set<BDTO> set);
Set<BDTO> bSetEntityToBDto(Set<B> set);
}
Below are the class definitions of ADTO and BDTO
public class ADTO implements Serializable {
private static final long serialVersionUID = 8307772637314390585L;
private Long aId;
private String aName;
private LocalDate startDate;
private LocalDate endDate;
private Set<BDTO> bs = new HashSet<>();
// Getters / Setters here
public void addToBs(BDTO b) {
if(b != null) {
bs.add(b);
}
}
// hashCode/equals/toString methods here...
}
public class BDTO implements Serializable {
private static final long serialVersionUID = 2562084231749296452L;
private Long bId;
private String name;
private LocalDate startDate;
private LocalDate endDate;
private String aName;
// getters / setters go here..
// hashCode/equals/toString methods here...
}
Below are the class definitions of entity classes, particularly pay attention to class B where the exception is related to.
#Entity
#Table(name = "TABLEB", uniqueConstraints = {
#UniqueConstraint(columnNames = "ID")})
public class B implements Serializable {
private static final long serialVersionUID = 1407209531508355406L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#Enumerated(EnumType.STRING)
#Column(name = "NAME", nullable = false)
private String name;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "A_ID", referencedColumnName="ID")
private A a;
#Column(name = "START_DATE", unique = false, nullable = false)
private LocalDate startDate;
#Column(name = "END_DATE", unique = false, nullable = false)
private LocalDate endDate;
}
#Entity
#Table(name = "TABLEA", uniqueConstraints = {
#UniqueConstraint(columnNames = "ID")})
public class A implements Serializable {
private static final long serialVersionUID = 6926335188960198569L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#Column(name = "NAME", unique = false, nullable = false, length = 100)
private String name;
#OneToMany(mappedBy="a"/*, fetch = FetchType.EAGER*/, cascade = {CascadeType.ALL})
private Set<B> bs = new HashSet<>();
#Column(name = "START_DATE", unique = false, nullable = false)
private LocalDate startDate;
#Column(name = "END_DATE", unique = false, nullable = false)
private LocalDate endDate;
}
I am just calling save method of ADao class that persists using entity Manager.

Spring Data Projection with OneToMany error

I have a entity call Circuit.
#Entity
public class Circuit implements Comparable<Circuit>, Serializable {
#Column
private String id;
#OneToMany(mappedBy = "circuit", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<Step> workflow = new HashSet<>();
...
}
I have a class called CircuitLight
public class CircuitLight {
private String id;
private Set<Step> workflow;
/* constructor, getters and setters */
}
In my CircuitRepository, i'm trying to make a projection
#Transactional(readOnly = true)
#Query("select new com.docapost.circuit.CircuitLight(c.id, c.workflow) from Circuit c where c.account.siren = :siren")
Set<CircuitLight> findAllByAccountSirenProjection(#Param("siren") String siren);
When i execute, i have a error message:
could not extract ResultSet; SQL [n/a] com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'circuit0_.id' in 'on clause'
I try with other entity. Every time i have a property with a relation #OneToMany, i have the issue...
Is it possible to make a projection with class (Without use a interface) when there are a relation OneToMany ?
UPDATE:
Step.class
#Entity
public class Step implements Comparable<Step>, Serializable {
private static final List<String> INDEXABLE_PROCESSES = Arrays.asList(
ParapheurWorkflowModel.SERVER,
ParapheurWorkflowModel.SIGN,
ParapheurWorkflowModel.VISA
);
#Id
#GeneratedValue
#Expose
#SerializedName("step_id")
public long id;
#ManyToOne
public Circuit circuit;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(joinColumns = #JoinColumn(name = "step_id"), inverseJoinColumns = #JoinColumn(name = "technicalGroup_id"))
private List<TechnicalGroup> technicalGroups = new ArrayList<>();
#Column(name = "step_type", nullable = false)
#Expose
#SerializedName("subprocess_ref")
public String type;
#Column(nullable = false)
public int orderIndex;
/* contructor, getters and setters */
}
UPDATE 2:
Hum.... My bad, in my circuit class, i have a EmbeddedId
#EmbeddedId
private CircuitPK key;
#Embeddable
public static class CircuitPK implements Serializable {
public String id;
public String siren;
}
I try with this code in Step.class
#ManyToOne
#JoinColumns(value = {
#JoinColumn(name = "circuit_siren", referencedColumnName = "siren"),
#JoinColumn(name = "circuit_id", referencedColumnName = "id")
})
public Circuit circuit;
The result is the same
Write the following code in the Step entity
#ManyToOne
#JoinColumn(name="id", nullable=false)
private Circuit circuit;

API Rest - OneToMany / ManyTone with JPA and Hibernate

I have the following relationship with this two entities
· Sport has Many SportTranslation
· SportTranslation belongsTo Sport
· Is Bidirectional
When I try to access from SportTranslation to Sport I recieve the following error.
java.lang.StackOverflowError: null
at java.util.AbstractCollection.toString(AbstractCollection.java:454) ~[na:1.8.0_191]
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
The error is not clear and the tables are not empty.
· I have the classical following Spring MVC architecture
The controller
#RestController
#RequestMapping("/api/public/sports")
public class SportController implements ISportsController {
Logger logger = LoggerFactory.getLogger(SportController.class);
#Autowired
private SportsMethods sportMethods;
#GetMapping(value = "/")
#Override
public ResponseEntity<List<SportDTO>> getSports(Pageable pageable) {
logger.info("--- Retrieve name of class --- : " +this.getClass().getSimpleName() + " --- Method name --- : " + new Object(){}.getClass().getEnclosingMethod().getName());
List<SportDTO> sportsMethodsList = sportMethods.retreiveListSports(pageable);
logger.info("--- Final list ---" + sportsMethodsList);
return new ResponseEntity<List<SportDTO>>(sportsMethodsList,
(sportsMethodsList == null || sportsMethodsList.isEmpty()) ? HttpStatus.NO_CONTENT : HttpStatus.OK);
}
}
· Class Methods
#Component
public class SportsMethods {
#Autowired
private SportService sportService;
public List<SportDTO> retreiveListSports(Pageable pageable) {
List<SportDTO> sportList = sportService.retreiveListSports();
return sportList;
}
}
· The service
#Component
public class SportService implements ISportService {
Logger logger = LoggerFactory.getLogger(SportService.class);
#Autowired
private SportRepository sportRepository;
#Autowired
private SportAdapter sportAdapter;
#Override
public List<SportDTO> retreiveListSports() {
List<Sport> sportList = sportRepository.findAll();
logger.info("--- Retrieve List Of Sports---"+sportList);
List<SportDTO > sportListDTO = sportAdapter.convertListSport2ListSportDTO(sportList);
logger.info("--- Retrieve a List Of SportsDTO" +sportListDTO);
return sportListDTO;
}
}
· The two adapters (SportAdatper , SportTranslationAdapter)
· SportAdapter
#Component
public class SportAdapter {
Logger logger = LoggerFactory.getLogger(SportAdapter.class);
#Autowired
private SportTranslationAdapter sportTranslationAdapter;
public List<SportDTO> convertListSport2ListSportDTO(List<Sport> sportList) {
logger.info("--- Sport List adapter" + sportList);
List<SportDTO> sportDTOList = new ArrayList<SportDTO>();
for (Sport sport : sportList) {
SportDTO sportDTO = new SportDTO();
sportDTO.setId(sport.getId());
sportDTO.setClave(sport.getClave());
sportDTO.setSportTranslationDTO(sportTranslationAdapter.convertSportTranslation2SportTranslationDTO(sport.getSportTranslation()));
sportDTOList.add(sportDTO);
}
logger.info("--- Sport DTO List adapter" + sportDTOList);
return sportDTOList;
}
· SportTranslationAdapter
#Component
public class SportTranslationAdapter {
Logger logger = LoggerFactory.getLogger(SportTranslationAdapter.class);
public List<SportTranslationDTO> convertSportTranslation2SportTranslationDTO(List<SportTranslation> list) {
List<SportTranslationDTO> sportTranslationDTOList = new ArrayList<SportTranslationDTO>();
for (SportTranslation sportTranslation : list) {
SportTranslationDTO sportTranslationDTO = new SportTranslationDTO();
sportTranslationDTO.setSportId(sportTranslation.getSport().getId());
sportTranslationDTO.setName(sportTranslation.getName());
sportTranslationDTOList.add(sportTranslationDTO);
}
return sportTranslationDTOList;
}
}
· Entities Sport and SportTranslation
· Sport
#Entity
#Table(name = "sport")
public class Sport implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sport_id")
private Long id;
#Column(name = "clave")
private String clave;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "sport_id")
private List<SportTranslation> sportTranslation;
·SportTranslation
#Entity
#Table(name = "sportstranslation")
public class SportTranslation implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sportstranslation_id")
private long idSportTranslation;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "sport_id", nullable = true)
private Sport sport;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "language_id", nullable = true)
private Language languageId;
#Column(name = "name")
private String name;
· Language is working correctly ,but this is not the problem the problem is with Sport.
Could anyone helps to me?
I would suggest your entity association to updated as below:
#Entity
#Table(name = "sport")
public class Sport implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sport_id")
private Long id;
#Column(name = "clave")
private String clave;
#OneToMany(mappedBy = "sport", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private List<SportTranslation> sportTranslation;
#Entity
#Table(name = "sportstranslation")
public class SportTranslation implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "sportstranslation_id")
private long idSportTranslation;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "sport_id", nullable = true)
private Sport sport;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "language_id", nullable = true)
private Language languageId;
#Column(name = "name")
private String name;
Also, annotate your service method in which you are fetching data with #Transactional.

Spring JPA: How to insert data to join many tables with #ManytoMany relationship

I'm starting to learn Spring Java Framework . I created some Enity to join 2 Model like my Database. And now I want to insert to Join Table by JpaRepository. What i have to do?
This is my Code (Please fix help me me if something is not right)
Model Users_RoomId to define Composite Primary Key
#Embeddable
public class Users_RoomId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "ID_room", nullable = false)
private String idRoom;
#Column(name = "user_id", nullable = false)
private int idUser;
}
Model Users_Room to join 2 Model Users and Room
#Entity
#Table(name ="bookroom")
public class Users_Room {
#EmbeddedId
private Users_RoomId usersroomId;
#ManyToOne
#MapsId("idRoom")
private Room room;
#ManyToOne
#MapsId("idUser")
private Users users;
#Column(name = "Bookday")
private String bookday;
Model Users and Room I used annotation #OneToMany
Model Users
#Entity
#Table(name = "users")
public class Users implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id", nullable = false)
private int id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "email")
private String email;
#Column(name = "pass")
private String pass;
#Column(name = "role")
private int role;
#OneToMany(mappedBy = "users")
private List<Users_Room> user;
Model Room
#Entity
#Table(name ="room")
public class Room implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID_room", nullable = false)
private String id;
#Column(name = "name_room", nullable = false)
private String name;
#Column(name = "Description")
private String describe;
#ManyToOne
#JoinColumn(name = "ID_status")
private Status status;
#Column(name = "room_image")
private String image;
public Room() {
super();
}
#ManyToOne
#JoinColumn(name = "ID_kind")
private KindRoom kind;
#OneToMany(mappedBy = "room")
private List<Users_Room> rooms;
This is my database
So I don't know how to insert a new bookroom with iduser,idroom and bookday with JPA repository.. It'necessary to write Query in JPARepository or We just need to use method save() to insert data
Thanks everyone
I had same problem and solved with following code. I used method save() to insert data. Following code is 'createRoom' method in 'RoomService.java'.
RoomService.java
private final RoomRepository roomRepository;
private final UserRoomRepository userRoomRepository;
private final UserRepository userRepository;
public RoomService(RoomRepository roomRepository, UserRoomRepository userRoomRepository, UserRepository userRepository) {
this.roomRepository = roomRepository;
this.userRoomRepository = userRoomRepository;
this.userRepository = userRepository;
}
#Transactional
public RoomDto createRoom(Long userId, Long chattingUserId) {
Room room = roomRepository.save(new Room());
room.addUserRoom(userRepository.findById(userId).orElseThrow(()->new NoSuchElementException("No User")));
room.addUserRoom(userRepository.findById(chattingUserId).orElseThrow(()->new NoSuchElementException("No User")));
userRoomRepository.save(new UserRoom(userRepository.findById(userId).orElseThrow(()->new NoSuchElementException("No User")),room));
userRoomRepository.save(new UserRoom(userRepository.findById(chattingUserId).orElseThrow(()->new NoSuchElementException("No User")),room));
RoomDto roomDto = RoomDto.of(room);
return roomDto;
}

Resources