This is a class which is created to mapping
#Column(name = "gender")
#Enumerated(EnumType.STRING)
private Gender gender;
Gender enum type created in local to map.
public enum Gender {
MALE,
FEMALE,
OTHER
}
swagger.yml
gender:
type: string
enum:
- MALE
- FEMALE
- OTHERS
This is mapper class
#Component
public class GuestMapper {
public GuestsEntity convertToGuestEntity(Guest guest) {
GuestsEntity newGuests = new GuestsEntity();
newGuests.setGender(guest.getGender());
}
I checked all the fields from entity and also checked from generated class. but didnt see any difference. Any help?
Related
I am using java+Spring framework+Hibernate for creating rest api but I have stumbled upon retrieving details of a table using foreign key attributes.
I have the following tables::
https://i.stack.imgur.com/lG7UR.png
I am retrieving all the ratings given using product id and then mapping to DTO, now I also want to populate the username using idusers as this is my foreign key.
Same is the case when I try to retrieve ratings given by the users, instead of displaying idproducts I want to display the product name and product description as It is a foreign key.
Any advice on how to do so using DTO's.
This is a perfect use case for Blaze-Persistence Entity Views.
Blaze-Persistence is a query builder on top of JPA which supports many of the advanced DBMS features on top of the JPA model. I created Entity Views on top of it to allow easy mapping between JPA models and custom interface defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure the way you like and map attributes(getters) via JPQL expressions to the entity model. Since the attribute name is used as default mapping, you mostly don't need explicit mappings as 80% of the use cases is to have DTOs that are a subset of the entity model.
Assuming you have an entity model like this
#Entity
public class User {
#Id
Integer id;
String role;
String username;
String password;
boolean enabled;
}
#Entity
public class Product {
#Id
Integer id;
String imageUrl;
String category;
int productPrice;
int productQuantity;
String productName;
String productDesc;
#OneToMany(mappedBy = "product")
Set<Rating> ratings;
}
#Entity
public class Rating {
#Id
Integer id;
int rating;
String review;
String ratingscol;
#ManyToOne(fetch = LAZY)
Product product;
#ManyToOne(fetch = LAZY)
User user;
}
A DTO mapping for your model could look as simple as the following
#EntityView(Rating.class)
interface RatingDto {
Integer getId();
UserDto getUser();
ProductDto getProduct();
}
#EntityView(User.class)
interface UserDto {
Integer getId();
String getUsername();
}
#EntityView(Rating.class)
interface ProductDto {
Integer getId();
String getProductName();
String getProductDesc();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
RatingDto dto = entityViewManager.find(entityManager, RatingDto.class, id);
But the Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
It will only fetch the mappings that you tell it to fetch
You can use ModelMapper when converting a DTO to an Entity bean and back from Entity bean to a DTO.
Add ModelMapper to your project
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.5</version>
</dependency>
Define the ModelMapper bean in your Spring configuration
#Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
Assuming the following models based on the given ER diagram you have given
public class UserDto {
Integer userId;
String role;
String username;
String password;
boolean enabled;
...default and parameterized constructor
...getter and setter methods
}
public class ProductDto {
Integer productId;
String imageUrl;
String category;
int productPrice;
int productQuantity;
String productName;
String productDesc;
...default and parameterized constructor
...getter and setter methods
}
public class RatingDto {
#Id
Integer id;
int rating;
String review;
String ratingscol;
ProductDto productDto;
UserDto userDto;
...default and parameterized constructor
...getter and setter methods
}
You can retrieve the ratings of a product using product id along with the user details by using the following method
#Repository
public interface RatingRepository extends JpaRepository<Rating, Integer>{
List<Rating> findByProduct_ProductId(Integer productId);
}
Then mapping rating objects to DTO
RatingDto ratingDto = modelMapper.map(rating, RatingDto.class);
Now you can retrieve username as following
ratingsDto.getUserDto().getUserName()
The same way you can retrieve the ratings by userId and access product details
When I run the below project, I receive the following error. How can I fix it?
Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract com.example.pharmanic.model.Rdhs_Hospital_Current_Stock com.example.pharmanic.repositories.Rdhs_Hospital_Current_StockRepository.findBysr_no(java.lang.String)! No property sr found for type Rdhs_Hospital_Current_Stock!
This is my Rdhs_Hospital_Current_Stock model class.
#Entity
#Data
#Table(name = "Rdhs_Hospital_Current_Stock")
public class Rdhs_Hospital_Current_Stock {
#Id
private Long batchId;
private int quantity;
private String expiredate;
#ManyToOne
private Hospital_By_Rdhs hospital_by_rdhs;
#ManyToOne
#JoinColumn(name = "sr_no", nullable = false, referencedColumnName = "sr_no")
private Medicine medicine;
}
sr_no is the foreign key of the Medicine table.
This is my Medicine entity:
#Data
#Entity
public class Medicine {
private #Id String sr_no;
private String name;
private String side_effect;
private String description;
public Medicine() {
}
public Medicine(String sr_no, String name, String side_effect, String description) {
this.sr_no = sr_no;
this.name = name;
this.side_effect = side_effect;
this.description = description;
}
}
When I use sr_no with my findBy() function:
#GetMapping("/rhstock/{id}")
ResponseEntity<?> getMedicine(#PathVariable String id){
Optional<Rdhs_Hospital_Current_Stock> rdhs_hospital_current_stock = Optional.ofNullable(rdhs_hospital_current_stockRepository.findBysr_no(id));
return rdhs_hospital_current_stock.map(response->ResponseEntity.ok().body(response)).orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
This is my repository:
public interface Rdhs_Hospital_Current_StockRepository extends JpaRepository<Rdhs_Hospital_Current_Stock,Long> {
Rdhs_Hospital_Current_Stock findBysr_no(String id);
}
Inspired from: Spring-Data-Jpa Repository - Underscore on Entity Column Name
The underscore _ is a reserved character in Spring Data query derivation (see the reference docs for details) to potentially allow manual property path description.
Stick to the Java naming conventions of using camel-case for member variable names and everything will work as expected.
Change sr_no to srNo.
Update repository function
Rdhs_Hospital_Current_Stock findBymedicine_srNo(String id);
I solve this error. I change in Reposity Interface & Controller class like as below
Repository Interface -:
#Query(value="select * from Rdhs_Hospital_Current_Stock h where h.sr_no = :sr_no",nativeQuery=true)
List<Rdhs_Hospital_Current_Stock> findBySr_no(#Param("sr_no")String sr_no);
Controller class -:
#RequestMapping(value = "/rhstocksr/{sr_no}", method = RequestMethod.GET)
List<Rdhs_Hospital_Current_Stock> getBatchByMedicine(#PathVariable("sr_no") String sr_no) {
return rdhs_hospital_current_stockRepository.findBySr_no(sr_no);
}
To keep using a derived query you may change sr_no to srNo.
You could solve this by starting using a native query, but my advice is to use derived querys everytime as it is possible to use it.
Spring-data-mongodb is trying to add createdDate to a null object and fails to do so. How do I configure spring audit to ignore null objects so it does not try to add audit fields to it?
I have an abstract class with all the audit info. Two classes (A,B) extend this abstract class and one of those two classes (A) has a reference to the other class (B) (that can be nullable). If I try to save an object of A with a null reference to B. It all fails because spring is trying to add audit info to the B null reference.
public abstract class AA {
#Id
private String id;
#Version
private Long version;
#CreatedDate
private LocalDateTime createdDate;
#LastModifiedDate
private LocalDateTime LastModifiedDate;
}
public class A extends AA {
private String name;
#Nullable
private B b;
}
public class B extends AA {
private String name;
}
public class ControllerA {
private AMongoRepository aMongoRepo;
public void saveSomeA(String name) {
A a = new A();
a.setName("Some Name");
a.setB(null);
aMongoRepo.save(a); // <-- Fails can not set createdDate on B null
}
}
The error message I get is the following.
org.springframework.data.mapping.MappingException: Cannot lookup property B A.b on null intermediate! Original path was: b.createdDate on A.
A quick google search brought me to jira.spring.io, which is the same issue I am having.
Any idea on how to cleanly handle this issue? Maybe move from inheritance to composition? Or should I just be patient an wait on the new version?
I use GraphQL SPQR with the entity
#Entity
public class MyEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
#GraphQLNonNull
#GraphQLQuery(name = "a", description = "Any field")
private String a;
// Getters and Setters
}
and the service
#Service
#Transactional
public class MyService {
#Autowired
private MyRepository myRepository;
#GraphQLMutation(name = "createEntity")
public MyEntity createEntity(#GraphQLArgument(name = "entity") MyEntity entity) {
myRepository.save(entity);
return entity;
}
}
In GraphiQL I am allowed to set the id:
mutation {
createEntity(entity: {
id: "11111111-2222-3333-4444-555555555555"
a: "any value"
}) {
id
}
}
But the id shall not be made editable to the user because it will be overwritten by the DB. It shall only be shown at the queries. I tried and added #GraphQLIgnore, but the id is shown all the same.
How can I hide the id at creation?
In GraphQL-SPQR version 0.9.9 and earlier, the private members are not scanned at all, so annotations on the private fields don't normally do anything. Incidentally, Jackson (or Gson, if so configured) is used to discover the deserializable fields on input types, and those libraries do look at private fields, so some annotations will appear to be working for input types. This is what is happening in your case. But, #GraphQLIgnore is not among the annotations that will work on a private field.
What you need to do is move the annotations to getters and setters.
#Entity
public class MyEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
#GraphQLIgnore //This will prevent ID from being mapped on the input type
//#JsonIgnore would likely work too
public void setId(UUID id) {...}
}
There's other ways to achieve this, but this is the most straight-forward.
Note: In the future versions of SPQR (post 0.9.9), it will be possible to place the annotations on private fields as well, but mixing (placing some annotations on a field and some on the related getter/setter) will not work.
Here's my class
public class JobSteps {
private String jobNo;
private String stepNumber;
private String stepDescription;
}
And here's my view
JobNo CHAR(7),
StepNumber TEXT,
StepDescription TEXT
I tried to annotate my class with Entity, specifying the table name, but spring keeps complaining about id, I added #Id to JobNo, but spring complains about type. Is there a way to manage it? I have no access to the view and can't change anything there.
Fo example, You can add JobStepId class and wrap tit with your char column.
#Embeddable
class JobStepId implements Serializable {
String jobIdString;
Integer jobId;
//implements equals and hashCode
}
Then your class could imbed it:
#IdClass(JobStepId.class)
public class JobSteps {
#Id
private JobStepId jobNo;
private String stepNumber;
private String stepDescription;
}