Why can't I access embedded properties in a mapper? - spring-boot

I have the following embedabble
#Data
#Embeddable
public class BaseEntity {
#CreatedDate
#Column(name = "created_date")
private LocalDateTime createdDate;
#CreatedBy
#Column(name = "created_by")
private String createdBy;
}
Which I embed into my entity like so
#Entity
#Data
#NoArgsConstructor
#Table(name = "participant")
public class Participant {
#Id
#GeneratedValue
private UUID id;
#Embedded
private BaseEntity baseEntity;
}
And in my mapper I want to access the embedded properties of the Participant like so
#Mapping(target = "createdDate", source = "participant.createdDate")
ParticipantDto entityToDto(Participant participant);
But I get the following error message
error: The type of parameter "participant" has no property named "createdDate".
As mapping source I tried participant.basicEntitity.createdDate which also results in the same error message as well as not specifying any mapping so mapstruct can automap, which also results in the property not found error message

Related

nested exception is org.hibernate.MappingException: Could not determine type for: Com.test.model.Client, at table: ComptePaiement

I'm using Hibernate in my spring project. But It doesn't work for One-To-One relationships. It gives me the below error.
Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: com.example.TransfertNational.model.Client, at table: ComptePaiement, for columns: [org.hibernate.mapping.Column(client)]
I have ran some searches in the internet, but it doesn't work for me.
the Client Entity :
#Data #Entity
#AllArgsConstructor #NoArgsConstructor #ToString
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String typeTransfert;
private String typePiece;
private String cin;
private String sexe;
private String prenom;
private String typePieceIdentite;
private String paysEmission;
private String numPI;
private String validitePI;
private String dateNaissance;
private String profession;
private String nationalite;
private String paysAdresse;
private String adresseLegale;
private String ville;
private String gsm;
private String email;
#OneToMany(fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
private Set<Beneficiaire> beneficiares;
#OneToOne(fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
private ComptePaiement comptePaiement;
}
the ComptePaiement Entity :
#Data
#Entity
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class ComptePaiement {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String solde;
private String rip;
private Client client;
}
Answer from comments:
You are probably missing #JoinColumn on Client or ComptePaiement and mappedBy in #OneToOne annotation, depending which will hold reference id in database.

Request processing failed; nested exception is java.lang.ClassCastException: Cannot cast java.lang.String to java.time.LocalDateTime] with root cause

I am using Java 1.8 & SpringBoot 2.3.4.RELEASE. I am trying to use the AuditingEntityListener and #MappedSuperclass features to populate the created_date and updated_date timestamps.
But I am getting this Exception: java.lang.ClassCastException: Cannot cast java.lang.String to java.time.LocalDateTime
I tried without #MappedSuperclass and it works.....but the created_date and updated_date fields are not getting populated.
Can anyone help me on this?
Here is the code snippet:
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class AuditableEntity implements Serializable {
#CreatedDate
#Column(name = "created_ts",nullable = false, updatable = false)
private LocalDateTime createdDate;
#LastModifiedBy
#Column(name = "updated_ts",nullable = false)
private LocalDateTime updatedDate;
#CreatedBy
#Column(name = "src_sys_cd",length = 15, updatable = false)
private String source;
#Version
#Column(name = "record_version_nb", length = 20, nullable = false)
private Long version;
}
----------------------------------
#Component
public class AuditorAwareImpl implements AuditorAware<String> {
#Value("${customer.service.source.code}")
private String auditor;
#Override
public Optional<String> getCurrentAuditor() {
return Optional.of(auditor);
}
}
----------------------------------
#Entity
#Setter
#Getter
#Builder
#Table(name = "customer_information")
#AllArgsConstructor
#NoArgsConstructor
public class CustomerEntity extends AuditableEntity {
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
}
#LastModifiedBy is used to set the current user when a modification happens. That is typically a String which can't be converted to anything date/time like and doesn't seem to be what you were looking for.
You should change this to:
#LastModifiedBy
#Column(name = "updated_ts",nullable = false)
private LocalDateTime updatedDate;
#LastModifiedDate
#Column(name = "updated_ts",nullable = false)
private LocalDateTime updatedDate;

Auto populate created_date, last_modified_date, created_by and last_modified_by in entity : Hibernate with JPA

I am new to Hibernate and JPA. I have several entities, each of which contains following four columns:
1. created_by
2. last_modified_by
3. created_date
4. last_modified_date
I would like these columns to get auto-populated while saving the associated entity.
Two sample entities are as follows:
Entity 1:
#Entity
#Table(name = "my_entity1")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity1 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
Entity 2:
#Entity
#Table(name = "my_entity2")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity2 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "description")
private String description;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
In this context, I have gone through following posts: How to autogenerate created or modified timestamp field?, How can you make a created_at column generate the creation date-time automatically like an ID automatically gets created?.
I am getting how to capture the dates fields but I cannot understand how to capture created_by and last_modified_by.
Auditing Author using AuditorAware and Spring Security...
To tell JPA about currently logged in user we will need to provide an
implementation of AuditorAware and override getCurrentAuditor()
method. And inside getCurrentAuditor() we will need to fetch currently
logged in user.
Like this:
public class AuditorAwareImpl implements AuditorAware<String> {
#Override
public String getCurrentAuditor() {
return "TestUser";
// Can use Spring Security to return currently logged in user
// return ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()
}
}
Now enable jpa auditing by using #EnableJpaAuditing
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class JpaConfig {
#Bean
public AuditorAware<String> auditorAware() {
return new AuditorAwareImpl();
}
}
Look at this to get more details....

spring data mongo No property b found on entity class when retrieving entity by Id

I have a parent class that has some shared fields and a child class that extends it.
#SuperBuilder(toBuilder = true)
#Data
public abstract class MultiTenantAuthoredDocument {
#Indexed
private String tenantId;
#CreatedDate
private LocalDateTime createdDate;
#LastModifiedDate
private LocalDateTime lastModifiedDate;
}
#Document(collection = "users")
#SuperBuilder(toBuilder = true)
#Data
#EqualsAndHashCode(callSuper = true)
#ToString(callSuper = true)
public class User extends MultiTenantAuthoredDocument {
#Id
private String id;
private String firstName;
private String lastName;
#Indexed
private String password;
#Indexed(unique = true)
private String userName;
#Indexed(unique = true)
private String email;
#Indexed
private List<UserRole> roles;
#Builder.Default
private boolean enabled = false;
}
However when running my unit tests, I get an unexpected exception when I do a findById and there's a result found namely:
No property b found on entity class be.moesmedia.erp.users.domain.User to bind constructor parameter to!
As I have no clue where property b is coming from it's pretty difficult to see what I'm doing wrong.
If anyone can help me point out what I'm doing wrong.
So I've figured out what was going wrong, Lombok generated a constructor that accepted an Object with the properties for the SuperBuilder class. Once I added #NoArgsConstructorto both the child and parent class, it works like a charm.

converting URI to entity with custom controller in spring data rest?

i have an jpa entity like this.
#Entity
#Table(name = "location")
#Data
public class Location {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "LOCATION_ID", unique = true)
#NotEmpty(message = "Please Enter Location ID")
private String name;
#Column(name = "LOCATION_DESCRIPTION")
#NotEmpty(message = "Please Enter Location Description")
private String description;
#ManyToOne
#NotNull(message = "Please Choose a Building")
Building building;
#Version
Long version;
}
and the repository like this.
public interface LocationRepository extends PagingAndSortingRepository<Location, Long> {
Location findByName(#Param("name") String name);
}
i am using spring data rest i am able to create location with rest api by providing the following payload
{
"name":"adminxxxxx","description":"adminxxx" , "building": "http://localhost:8080/buildings/2"
}
now i am trying to write my custom controller which will persist the entity. this is my custom controller
#ExposesResourceFor(Location.class)
#RepositoryRestController
#BasePathAwareController
public class LocationController {
#Autowired
LocationRepository locationDao;
#Autowired
LocationResourceAssembler resourceAssembler;
#Value("${buildings.error.messages.uniqueconstraintviolation}")
String uniqueConstrainMessage;
static final String TAG = LocationController.class.getSimpleName();
#RequestMapping(value="locations",method = org.springframework.web.bind.annotation.RequestMethod.POST)
public ResponseEntity<?> save(#RequestBody #Valid Location location) {
try {
location = locationDao.save(location);
LocationResource b = resourceAssembler.toResource(location);
return ResponseEntity.ok().body(b);
} catch (DataIntegrityViolationException e) {
if (locationAlreadyExists(location.getName()))
throw new LocationAlreadyExistException(uniqueConstrainMessage, location);
else
throw new RuntimeException("Some Error Occured");
}
}
i am getting this error
exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.alamdar.model.Building: no String-argument constructor/factory method to deserialize from String value ('http://localhost:8080/buildings/2')
at [Source: java.io.PushbackInputStream#5d468b16; line: 3, column: 60] (through reference chain: com.alamdar.model.Location["building"])</div></body></html>
can anyone please help?
I am not sure why you are writing a custom controller however the issue would appear to be that you do not have a default no args constructor so Jackson cannot instantiate an instance.
This is because you are using Lombok's #Data annotation:
https://projectlombok.org/features/Data.html
You should also annotate you class with #NoArgsConstructor to have a default no-args constructor generated:
#Entity
#Table(name = "location")
#Data
#NoArgsConstructor
public class Location {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "LOCATION_ID", unique = true)
#NotEmpty(message = "Please Enter Location ID")
private String name;
#Column(name = "LOCATION_DESCRIPTION")
#NotEmpty(message = "Please Enter Location Description")
private String description;
#ManyToOne
#NotNull(message = "Please Choose a Building")
Building building;
#Version
Long version;
}

Resources