Why I am receiving empty array? - spring

I am doing a project in Spring and Postgres. I am getting this empty column when I try to call a request with Postman. As you can see, it returns everything except ingredient column.
{
"recept_id": 8,
"recept_name": "conceptual",
"nation_id": 1,
"type_id": 1,
"isvegan": true,
"isvegetarian": true,
"photo": null,
"video": null,
"ingredient": [],
"level_id": 5,
"recept_view": 1,
"company_id": 4,
"ratinglvl": 5
}
However, in Postgres, this column has data ({1,2,3}). The data type of the ingredient column is an integer[] in Postgres. I inserted data to ingredient to Postgres manually.
While in Spring, I am using a simple CRUDrepository.
Entity:
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "recept")
public class Recept {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long recept_id;
#Column
private String recept_name;
private long nation_id;
private long type_id;
private boolean isvegan;
private boolean isvegetarian;
private File photo;
private File video;
#ElementCollection(targetClass=Long.class)
private List<Long> ingredient;
private short level_id;
private long recept_view;
private long company_id;
private short ratinglvl;
}
Controller:
#RestController
public class ReceptController {
private final ReceptService receptService;
public ReceptController(ReceptService receptService) {
this.receptService = receptService;
}
#RequestMapping(value="/recept",method= RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity<?> getAll() {
return ResponseEntity.ok(receptService.getAll());
}
Repository:
public interface ReceptRepository extends CrudRepository<Recept, Long> {}
Service:
#Service
public class ReceptService {
private final ReceptRepository receptRepository;
private final IngredientRepository ingredientRepository;
public ReceptService(ReceptRepository receptRepository, IngredientRepository ingredientRepository) {
this.receptRepository = receptRepository;
this.ingredientRepository = ingredientRepository;
}
public List<Recept> getAll(){
return (List<Recept>)receptRepository.findAll();
}
Don't know why it doesn't return it.

#ElementCollection is meant to collect the values of a column in a related table -not to denote a PostgreSQL array type.
In order to use Postgresql arrays, you need to define a custom type. Thankfully the hibernate-types library already provides a ListArrayType out of the box. This will allow you to define your entity like:
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#TypeDef(
name = "list-array"
typeClass = ListArrayType.class
)
#Table(name = "recept")
public class Recept {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long recept_id;
#Column
private String recept_name;
private long nation_id;
private long type_id;
private boolean isvegan;
private boolean isvegetarian;
private File photo;
private File video;
#ElementCollection(targetClass=Long.class)
#Type(type = "list-array)
#Column(
name = "ingredient",
columnDefinition = "integer[]"
)
private List<Long> ingredient;
private short level_id;
private long recept_view;
private long company_id;
private short ratinglvl;
}

Related

Post Request with Enum and composite key

I'm working on an exercise where i have to create CRUD operations.
I have a User table, a Role table and a UserRole table where i have the primary keys of those two entities.
I also have a RoleEnum with roles that have to be assigned to the User.
The problem that i'm gettin is that every time I insert a new user is a 200ok response but the role returns null and so it doesn't add it to the UserRole table as well.
I need help in solving the problem.
User Entity
#Data
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "utente")
public class Utente implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long matricola;
#Column(nullable = false)
private String nome;
#Column(nullable = false)
private String cognome;
#Column(nullable = false)
private String email;
#Column(name = "ruoloUtente", nullable = false)
#OneToMany(mappedBy = "matricolaUtente")
#JsonIgnore
private List<UtenteRuolo> ruoloUtente;
}
Role Entity
#Data
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "ruolo")
public class Ruolo implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "tipo_ruolo")
private String nome;
#Column(name = "utente_ruolo")
#OneToMany(mappedBy = "nomeRuolo")
private Set<UtenteRuolo> utenteRuolo;
}
UserRole class
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "utente_ruolo")
public class UtenteRuolo implements Serializable {
#EmbeddedId
private UtenteRuoloId utenteRuoloId;
#ManyToOne
#MapsId("matricola")
#JoinColumn(name = "matricola_utente", nullable = false)
private Utente matricolaUtente;
#ManyToOne
#MapsId("id")
#JoinColumn(name = "nome_ruolo", nullable = false)
private Ruolo nomeRuolo;
}
UserRoleId class
#Embeddable
#Data
#EqualsAndHashCode
#AllArgsConstructor
#NoArgsConstructor
public class UtenteRuoloId implements Serializable {
#Column(name = "matricola")
private Long matricola;
#Column(name = "id")
private Long id;
}
RoleEnum class
public enum RuoliEnum {
#JsonProperty
REFERENTE("REFERENTE"),
CONSULTATORE("CONSULTATORE"),
APPROVATORE("APPROVATORE");
#JsonProperty
private String value;
RuoliEnum(String value) { this.value = value; }
#JsonCreator
public static RuoliEnum fromValue(String text) {
for (RuoliEnum ruoli: RuoliEnum.values()) {
if (String.valueOf(ruoli.value).equalsIgnoreCase(text.trim())) {
return ruoli;
}
}
return null;
}
}
I also have all DTO's and the UserDTO has the RoleEnum instead of the List of class UserRole.
UserService
#Service
public class UtenteService {
#Autowired
private UtenteRepository utenteRepository;
#Autowired
private UtenteMap utenteMap;
public UtenteDto addUtente(UtenteDto utente) {
Utente u = utenteMap.fromDtoToModel(utente);
if(u != null) {
return utenteMap.fromModelToDto(utenteRepository.save(u));
}
return null;
}
UserController
#RestController
#RequestMapping("utente")
public class UtenteController {
#Autowired
private UtenteService utenteService;
#PostMapping("/addUtente")
public ResponseEntity addUtente(#Nullable #RequestBody UtenteDto utente) {
if(utente != null) {
return ResponseEntity.ok(utenteService.addUtente(utente));
} else {
return ResponseEntity.badRequest().body("utente non inserito correttamente");
}
}
this is a postman insert example:
{
"matricola" : 11,
"nome" : "aaa",
"cognome" : "bb",
"email" : "eee#mail.com",
"ruolo" : "APPROVATORE"
}
and this is the postman response with 200ok status:
{
"matricola": 11,
"nome": "aaa",
"cognome": "bb",
"email": "eee#mail.com",
"ruolo": null
}
the code doesn't tell me about any kind of error and i need to keep the UserRole table because it's required for this kind of exercise.
I tried everything I could but since I never worked like this with enums and this kind of table relations I don't know what's missing to complete it.

Spring JPA - How can I make JpaRepository queries using an #Embedded property?

I'm trying to make a existsBy query using a property that comes from an embedded class, but I'm receiving "No property 'cpf' found for type 'Patient'".
The class Patient uses the Person class as embedded.
Person.java
#Embeddable
#Data
public class Person {
#Column(nullable = false, length = 11)
private String cpf;
#Column(name = "full_name", nullable = false, length = 60)
private String fullName;
#Column(nullable = false)
private String birthdate;
#Column(name = "email", nullable = true, length = 30)
private String emailAddress;
#Column(name = "cellphone_number", nullable = true, length = 11)
private String cellphoneNumber;
}
Patient.java
#Data
#Entity
#Table(name = "tb_patient")
public class Patient implements Serializable {
#Serial
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "patient_id")
private UUID id;
#Column
private LocalDateTime registrationDate;
#Embedded
private Person Person;
}
PatientController.java (part of)
#PostMapping
public ResponseEntity<Object> savePatient(#RequestBody Person person) {
if(patientService.existsByCpf(person.getCpf())) {
return ResponseEntity.status(HttpStatus.CONFLICT).body("CONFLICT: CPF number is already in use!");
}
var patientModel = new Patient();
BeanUtils.copyProperties(person, patientModel);
patientModel.setRegistrationDate(LocalDateTime.now(ZoneId.of("UTC")));
return ResponseEntity.status(HttpStatus.CREATED).body(patientService.save(patientModel));
}
PatientService.java (part of)
#Service
public class PatientService {
final PatientRepository patientRepository;
public PatientService(PatientRepository patientRepository) {
this.patientRepository = patientRepository;
}
public boolean existsByCpf(String cpf) {
return patientRepository.existsByCpf((cpf));
}
PatientRepository.java
#Repository
public interface PatientRepository extends JpaRepository<Patient, UUID> {
boolean existsByCpf(String cpf);
}
How can I pass the #Embedded properties to the #Repository?
You can try separate by _ embedded filed name and it's filed.
#Repository
public interface PatientRepository extends JpaRepository<Patient, UUID> {
boolean existsByPerson_Cpf(String cpf);
}

How Can I mapping DTOs using mapstruct?

I am tring to mapping entity datas to DTOs using mapstruct.
And with these sources, I could map id,title datas.
But the problem is.... I can not map userName using these sources.
How can I resolve this problem??
#Entity // DB와의 연결을 위하여
#Data // getter setter
public class Board {
#Id // id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Size(min=2, max=30)
private String title;
#Length(min=20)
#Lob
#Column(columnDefinition="TEXT", nullable = false)
private String content;
#ManyToOne
#JoinColumn(name="userId", referencedColumnName = "id")
private User user;
}
#Builder
#AllArgsConstructor
#Data
public class BoardListDto {
private Long id;
private String title;
private String userName;
}
#Mapper(componentModel = "spring")
public interface BoardListMapper extends EntityMapper<BoardListDto, Board> {
#Override
#Mapping(target = "userName", source = "user.name.value")
List<BoardListDto> toDtos(List<Board> board);
}
public interface EntityMapper <D, E> {
E toEntity(D dto);
D toDto(E entity);
// Entity업데이트 시 null이 아닌 값만 업데이트 하도록 함.
#BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void updateFromDto(D dto, #MappingTarget E entity);
List<D> toDtos(List<E> entity);
}
no need to implement toDtos method for this. This code should be enough and Mapstruct will handle the rest alone.
#Mapper(componentModel = "spring")
public interface BoardListMapper extends EntityMapper<BoardListDto, Board> {
#Override
#Mapping(target = "userName", source = "user.name")
BoardListDto toDto(Board board);
}

Why I can't delete data in cascade way?

The problem is when I want to delete user I'm getting error in Spring Boot like that:
java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (32506632_pam.badge, CONSTRAINT FK4aamfo6o0h5ejqjn40fv40jdw FOREIGN KEY (user_id) REFERENCES user (id))
I'm guessing that I need to delete data in cascade way. So I've placed CascadeType.REMOVE value to #OneToOne annotation like that, but it doesn't work:
badge entity
#Entity
#Data
#Table(name = "badge")
#AllArgsConstructor
#NoArgsConstructor
public class Badge {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#JsonManagedReference
#ManyToMany(mappedBy = "badges", fetch = FetchType.LAZY)
private List<Reader> readers;
#OneToOne(cascade = CascadeType.REMOVE, orphanRemoval=true)
#JoinColumn(name = "user_id")
private User user;
private String number;
#Lob
#Basic(fetch = FetchType.LAZY)
private byte[] photo;
}
user entity
#Entity
#Data
#Table(name = "user")
#AllArgsConstructor
#NoArgsConstructor
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String lastname;
private String pesel;
private String email;
private String telephone;
private Integer age;
private String gender;
}
reader entity
#Entity
#Data
#Table(name = "reader")
#AllArgsConstructor
#NoArgsConstructor
public class Reader {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#JsonBackReference
#ManyToMany(fetch = FetchType.LAZY)
private List<Badge> badges;
private String department;
private String room;
private Boolean status;
}
Class which loads initial data
#Component
public class DataLoader implements ApplicationRunner {
#Autowired
private UserService userService;
#Autowired
private BadgeService badgeService;
#Autowired
private ReaderService readerService;
#Override
public void run(ApplicationArguments args) throws Exception {
User user1 = new User(null, "Jan", "Kowal", "11111111111", "jan#kowal.pl", "+48111111111", new Integer(23), "male");
userService.saveUser(user1);
Reader reader1 = new Reader(null, null, "Warehouse", "207A", new Boolean("true"));
Badge badge1 = new Badge(null, Arrays.asList(reader1), user1, "738604289120", null);
badgeService.saveBadge(badge1);
reader1.setBadges(Arrays.asList(badge1));
readerService.saveReader(reader1);
}
}
Endpoint for deleting user - it uses repository which extends CrudRepository and uses default delete behavior.
#DeleteMapping("/deleteUserById/{id}")
private void deleteUserById(#PathVariable Long id) {
userService.deleteUserById(id);
}
Database structure in phpmyadmin
My goal is to delete user and associated badge with him, then to delete row in reader_badges table.

AuditingEntityListener is not working for the entity that extends another abstract entity in spring jpa

I have used the #CreatedBy, #CreatedDate, #LastModifiedBy, and #LastModifiedDate annotation on their respective fields. By using #MappedSuperclass,#EntityListeners i able to persist above columns.
But this is not working for the below case:
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class Auditable<U> {
#CreatedBy
protected U createdBy;
#CreatedDate
#Temporal(TIMESTAMP)
protected Date creationDate;
#LastModifiedBy
protected U lastModifiedBy;
#LastModifiedDate
#Temporal(TIMESTAMP)
protected Date lastModifiedDate;
}
#Entity
#Table(name = "tabel1")
#PrimaryKeyJoinColumn(name = "ID")
class A extends B {
#Column(name = "NAME1", nullable = false)
private String name1;
#Column(name = "CONTENT1", nullable = false)
private String content1;
}
#Entity
#Table(name = "tabel2")
public abstract class B extends Auditable{
#Id
#GeneratedValue
#Column(name = "ID", nullable = false)
private int id;
#Column(name = "NAME", nullable = false)
private String name;
#Column(name = "CONTENT", nullable = false)
private String content;
}
AuditorAwareImpl.java
public class AuditorAwareImpl implements AuditorAware<String>
{
#Override
public Optional<String> getCurrentAuditor()
{
return Optional.ofNullable("Saravanan");
}
}
JpaAuditConfiguration.java
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class JpaAuditConfiguration
{
#Bean
public AuditorAware<String> auditorProvider()
{
return new AuditorAwareImpl();
}
}
In the case, Entity B is populated with audit columns. But Entity A is not. Is there a way to populate Entity A or did i missed anything here..??
I added #Entity annotation to your classes:
#Entity
public class A extends B {
#Id
#GeneratedValue
private Integer id;
private String name;
private String content;
}
#Entity
public class B extends Auditable<String> {
#Id
#GeneratedValue
private Integer id;
private String name;
private String content;
}
Persistence config class (for Spring Boot):
#Configuration
#EnableJpaAuditing
public class PersistenceConfig {
}
Everything works perfectly!

Resources