Convert an object attribute to mapstruct - spring-boot

My DTO:
public class ObjectDTO implements Serializable {
private Long id;
private String title;
private Long parentId;
...
}
My Entity:
public class MyObject implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
#Column(name = "id")
private Long id;
#Column(name = "title")
private String title;
#Column(name = "parent_id")
#ManyToOne
private MyObject parent;
....
}
My Mapper:
#Mapper(componentModel = "spring")
public interface ObjectMapper extends EntityMapper<ObjectDTO, MyObject> {
#Mapping(target = "parentId", source = "m.parent.id")
ObjectDTO toDto(MyObject m);
}
Exception:
error: Can't map property "Long parentId" to "MyObject parentId". Consider to declare/implement a mapping method: "MyObject map(Long value)". Occured at 'E toEntity(D dto)' in 'EntityMapper'.
Please tell me what is the reason, and what are the correct actions when extracting the attribute
UPDATE:
This is my interface for Mapper
public interface EntityMapper<D, E> {
E toEntity(D dto);
D toDto(E entity);
}

just do what mapstruct is telling you to do: you are missing a method with signature MyObject map(Long value) needed by autogenerated toEntity() method for property mapping ObjectDTO.parentId mapped to MyObject.parent.
Check MapStruct Object factories; them may be the right way to solve your problem.

Related

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);
}

JPA Specification filtering nested object

I am trying to fetch nested object property but getting illegalArgument exception.
AuditTestingPlanSpecification name = new AuditTestingPlanSpecification(new SearchCriteria("auditPlanId.auditPlanEntity", ":",dates));
Page<AuditTestingPlanMaster> a = auditTestingPlanMasterRepository.findAll(name, ten);
Please find below code,
public class AuditTestingPlanSpecification implements Specification<AuditTestingPlanMaster> {
private SearchCriteria criteria;
public AuditTestingPlanSpecification(SearchCriteria searchCriteria) {
this.criteria = searchCriteria;
}
#Override
public Predicate toPredicate(Root<AuditTestingPlanMaster> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
if (root.get(criteria.getKey()).getJavaType() == String.class) {
return builder.like(root.<String>get(criteria.getKey()), "%" + criteria.getValue().get(0).toString() + "%");
} else {
return builder.equal(root.get(criteria.getKey()), criteria.getValue().get(0).toString());
}
return null;
}
}
Class SearchCriteria.java
public class SearchCriteria {
public SearchCriteria(String key, String operation, List<Object> value) {
super();
this.key = key;
this.operation = operation;
this.value = value;
}
private String key;
private String operation;
private List<Object> value;
// getters & setters
}
Class AuditTestingPlanMaster.java
#Entity
#Table(name = "audit_testing_plan_master")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class AuditTestingPlanMaster implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "risk_area_id")
private Long riskAreaId;
#Column(name = "expected_revert_date")
private Instant expectedRevertDate;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private Instant lastModifiedDate;
#JoinColumn(name = "audit_plan_id", referencedColumnName = "id")
private AuditPlanMaster auditPlanId;
//getters & setters
}
Class AuditPlanMaster.java
#Entity
#Table(name = "audit_plan_master")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class AuditPlanMaster implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "remarks", length = 255)
private String remarks;
#Column(name = "audit_plan_entity", length = 50)
private String auditPlanEntity;
#Column(name = "start_date")
private Instant startDate;
#Column(name = "end_date")
private Instant endDate;
//getters & setters
}
I want to fetch all the AuditTestingPlanMaster objects whose AuditPlanMaster.auditPlanEntity string is matching with provided filter value.
Thank you for your time and help in advance.
I had the same problem, here is a snippet of how I handled it. My problem was when accessing id field from inner usuario object, in my case, id would be like your auditPlanEntity, and usuario would be like auditplanMaster:
public static Specification<UsuarioErrorEquipo> usuarioContains(String codigoUsuario) {
return (root, query, builder) -> {
Path<Usuario> u = root.get("usuario");
return builder.equal(u.get("id"), codigoUsuario);
};
}
I believe, that in your case it should be something like:
Path<AuditPlanMaster> u = root.get("auditPlanId");
return builder.equal(u.get("auditPlanEntity"), "the value you want to compare");

Spring JPA Update Entity

I'm trying to update my user entity and I have an error that comes to mind:
ERROR: A NULL value violates the NOT NULL constraint of the "id" column Detail: The failed row contains (null, 1, 1)
The problem surely stems from my relationship between user and profile which is n-n
public class Utilisateur implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Integer id;
private Integer fixe;
private Boolean deleted;
private Boolean actif;
private String email;
private Integer mobile;
private String motDePasse;
private String nom;
private String prenom;
#ManyToMany
private List<Profil> profils = new ArrayList<Profil>();
public Utilisateur() {
}
}
public class Profil implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Integer id;
private String codeProfil;
private String libelleProfil;
#JsonManagedReference
#ManyToMany
private List<MenuAction> menuActions = new ArrayList<MenuAction>();
public Profil() {
}
}
How you generate value for your id?
Seems you need some way to generate value for you ID.
For example, use #GeneratedValue, like:
#GeneratedValue(strategy = IDENTITY)

How to lazy fetch with spring data repository?

Database Tables
post
tag
ref_post_tag
post and tag has a Many-to-Many relationship
Entities
Post
#Entity
#Table(name = "post")
public class Post implements Serializable{
private static final long serialVersionUID = 1783734013146305964L;
public enum Status {
DRAFT, REMOVED, LIVE;
}
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private String id;
#Column(name = "title")
private String title;
#Column(name = "create_time")
private LocalDateTime createTime;
#Column(name = "update_time")
private LocalDateTime updateTime;
#Column(name = "content")
private String content;
#Column(name = "status")
#Enumerated(EnumType.STRING)
private Status status;
#ManyToMany
#JoinTable(
name = "ref_post_tag",
joinColumns = #JoinColumn(name="post_id",referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name="tag_id", referencedColumnName = "id"))
private List<Tag> tagList;
...
}
Tag
#Entity
#Table(name="tag")
public class Tag implements Serializable{
private static final long serialVersionUID = -7015657012681544984L;
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name="name")
private String name;
#Column(name="description")
private String description;
#ManyToMany(mappedBy = "tagList")
private List<Post> postList;
public Integer getId() {
return id;
}
...
}
Tag Repo
public interface TagRepo extends CrudRepository<Tag, Integer>{
}
service implementation
#Service
public class TagServiceImpl implements TagService{
#Autowired
private TagRepo tagRepo;
#Override
public void addTag(Tag tag) {
tagRepo.save(tag);
}
#Override
public Tag getTag(Integer id) {
Tag tag = tagRepo.findOne(id);
return tag;
}
#Override
public List<Tag> findAllTags() {
return CollectionUtil.toArrayList(tagRepo.findAll());
}
}
sample test (Updated)
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestContextConfiguration.class)
#Transactional
public abstract class ServiceTest {
}
public class TagServiceTest extends ServiceTest{
#Autowired
private TagService tagService;
#Autowired
private TagRepo tagRepo;
#Test
#Transactional
public void addTag() throws Exception {
Tag tag = new Tag();
tag.setName("new tag");
tag.setDescription("this is a new tag");
tagService.addTag(tag);
Tag tagCreated = tagRepo.findOne(tag.getId());
assertNotNull(tagCreated);
assertEquals(tagCreated.getName(), tag.getName());
}
#Test
public void getTag() throws Exception {
Tag tag = tagService.getTag(1); // tag "java" has an ID of "1"
assertNotNull(tag);
assertEquals(tag.getName(), "java");
assertEquals(143,tag.getPostList().size()); // 143 posts under tag "java"
}
}
Question
The sample test case passes. It means that the postList in fetched Tag is also eagerly fetched and filled.
Is Spring data repository's methods eagerly fetching by default?
If yes, what is the best way to change this to lazy fetching?

Resources