How to prove JPA Enity must not be final class with Hibernate 5 - jpa-2.1

JSR 338: JavaTM Persistence API 2.1 Specification > 2.1 The Entity Class specifies:
The entity class must not be final. No methods or persistent instance variables of the entity class may be final.
So I tried with Hibernate 5.2.18.Final to prove it by setting an entity class as final:
#EqualsAndHashCode
#Getter
#Setter
#Entity
public final class City {
#Id
#SequenceGenerator(name="city_sequence", sequenceName="city_seq", initialValue=0, allocationSize=25)
#GeneratedValue(strategy=SEQUENCE, generator="city_sequence")
private int id;
#Column(length=20, nullable=false)
private String city;
#ManyToOne(fetch = FetchType.LAZY)
private Province province;
}
However, the result is out of my expectation: the corresponding table can be generated and new instance of City can be persisted to the database, meaning my code proves that entity class can be final
Question: Is there any better way to prove the entity class must not be final? Isn't it a hard-and-fast rule as it is in the specification?

Related

Convert Spring Entity objects to modified JSON Object

I am having a few tables in my DB. Employee, Address, Phone_id
Table Employee
====================
ID | Emp_Name | Address_id | Phones_id
Table Address
====================
ID | Block_no | City | State
Table Phone_id
====================
ID | Phone_1 | Phone_2 | Phone_3
When I display the JSON received directly from repository, it works, but not in the format expected by UI.
I wish to make some changes to the received JSON. Basically, transform it and then provide response over REST.
So my questions are:
Is there any Spring way to solve my requirement. So that I can just map my entity class to some JSON class.
Is there any design pattern that can be used in such a scenario.
Thanks a bunch!
It is advisable to keep you #Entity classes and your JSON representation classes separated.
Let's say you have #Entity class Employee.
One option is to use the same Employee class to describe your database entity (using let's say JPA annotations) and then use the same Employee class to describe the JSON you want to return to the client (using let's say Jackson annotations).
That's considered bad practice for various reasons.
Most common one is that most of the time you don't want all your entities to be mapped 1:1 to your JSON response.
In order to deal with this, a common approach is to create a separate Employee class to describe your JSON representation. You can call it EmployeeDto.
Then you have to write a custom logic that maps #Entity Employee to EmployeeDto.
You can use static factory method like so:
//Persistence layer class
#Entity
public class Employee {
#Id
#GeneratedValue
#Column(name = "id")
private Long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
//getters/setters
}
//REST layer class
public class EmployeeDto {
#JsonProperty("first_name")
private String firstName;
#JsonProperty("last_name")
private String lastName;
public EmployeeDto() {}
// you can do any transforamtion/validation here
public static EmployeeDto fromEntity(Employee employee){
EmployeeDto dto = new EmployeeDto();
dto.setFirstName(employee.getFirstName);
dto.setLastName(employee.getLastName);
}
//getters/setters
}
Then your controller will return List<EmployeeDto> instead of #Entity Employee.
UPDATE:
Spring doesn't provide automatic conversion mechanism between DTO and Entity object. I think it depends on the complexity of the classes and number of pairs (DTO/Entity), but most of the time it's easy enough to implement the conversion yourself.
Of course there are libraries out there, which provide some level of automation with the mapping:
ModelMapper
Orica

Spring Data JPA method for deleting using a two fields in the embaddable key

THis is the main entity class, which is having an embeddedId
public class LabResHivMutation implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private LabResHivMutationPK id;
private String comments;
#Column(name="MUTATION_TYPE_ID")
private BigDecimal mutationTypeId;
#Column(name="VALUE")
private String value;
}
This is the embeddable key
#Embeddable
public class LabResHivMutationPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#Column(name="TO_INST")
private Long toInst;
#Column(name="REL_INVSTID")
private long relInvstid;
#Column(name="MUTATION_ID")
private long mutationId;
}
Is there any delete methos available in spring data Jpa to delete based on only two of the embaddable key(toInst,relInvstid).
I still can write a JPQL query to delete it. My question is there any method available for this.
like deleteById ?
Yes there is, repo.deleteByIdToInstAndIdRelInvstid(toInst,relInnvstid)
As you see you have to specify deleteByIdToInst , this is how you reference a field of an embedded ID , the same as you would reference a field of a foreign relation. Here Id matches your field naming
#EmbeddedId
private LabResHivMutationPK id;
There are two ways to delete an entity: either using its own "JPA Repository derived delete method" long deleteByFirstIdAndSecondId(long firstId , secondId)
In your service you can simply call it : repository.deleteByFirstIdAndSecondId(long firstId , secondId)
Another way is through the parent entity by excluding the child entity (or entities depends on the relation type).
User underscore '_' when entity will have multiple keys with using #Embedded keys.
example :repository.deleteByid_toInst();

Nested entity in request body is ignored

The domain model is
An industry has many companies
A company belongs to an industry
So I have my entity classes:
#Entity
public class Industry {
#Id #GeneratedValue
private Long id;
private String name;
#OneToMany(targetEntity = Company.class, fetch = FetchType.LAZY, mappedBy = "industry")
private Collection<Company> companies = new ArrayList<>(0);
// Getters and setters
}
and
#Entity
public class Company {
#Id #GeneratedValue
private Long id;
private String name;
#ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.EAGER, optional = false)
private Industry industry;
// Getters and setters
}
My controller:
#RestController
#RequestMapping("/companies")
public class CompaniesController extends ControllerBase {
#RequestMapping(method = RequestMethod.POST)
public Company create(#RequestBody Company company) {
company.getIndustry(); // returns null
// ...
}
}
When I send request POST /companies with request body
{
"name": "Walmart",
"industry": {
"id": 1
}
}
I found that company.getIndustry() always returns null. How can I make the controller accept nested entities?
Entities are session based. They usually work on basis of Lazy loading I.e only the first level is loaded and other attributes are loaded on Demand. You cannot pass it from one layer to other. (service to controller)
The correct way to do it. Have a Value object (a simple class) n the controller. Use it between front end and back end. Send the same value object to service. And use the entity only between Service and DAo layer
public class CompanyVO{
private Long id;
private String name;
private IndustryVO industryVO; // create similar class
// Getters and setters
}
#RestController
#RequestMapping("/companies")
public class CompaniesController extends ControllerBase {
#RequestMapping(method = RequestMethod.POST)
public Company create(#RequestBody CompanyVO companyVO) {
companyVO.getIndustry(); // returns null
// ...
}
}
This may be because you need another Spring message converter instead of the default one. Just add jackson to your pom.xml and Spring will use MappingJackson2HttpMessageConverter.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>

Spring Data Jpa: save an entity with #ManyToOne

I m working with spring boot, i have these two classes
#Entity
#Table(name="products")
public class Product implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idProduit;
//other attributes..
#ManyToOne
#JoinColumn(name="idCategory")
private Category category;
and category class :
#Entity
public class Category implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idcategory;
//attributes...
#OneToMany(mappedBy="category")
private Collection<Product> products;
i want to code a methode to save product
public long saveProduct(Product p, Long idCat)
Is there a method defined in JpaRepository which can do this or, should i add a service Layer and define my method like below or define it a custom method in Repository ?
public long saveProduct(Product p, Long idCat){
Category c=getCategory(idCat);
p.setCategory(c);
em.persist(p);
return p.getIdProduct();
}
I think you should add a service Layer and define a transactional method in order to handle exceptions like CategoryNotFoundException (when Category c=getCategory(idCat) fires one) ,
DataIntegrityViolationException....
Building a solution without a service Layer isn't a good practice, since you will have to handle transactions and propagations manually and you will risk having dirty reads.

Mockito and EJB

Good evening everybody,
I have a EJB class. This class has 2 attributes are EJB, with private access, and "injected" with EJB annotation #EJB. This class has no defined constructor.
I want to test this class by using Mockito.
I have 2 problems :
1) the 2 attributes are with private access
2) Even when i want to put a defined constructor with the 2 EJB attributes as parameters, it does not work in my TestNG class
In my TestNG class,
i only want instantiate my class of course,
and also her 2 EJB attributes as 2 mocks.
And i do not succeed.
Thank you very much,
Thomas
This is the class.
package fr.nomenclature.service;
#Stateless
#Local
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class TraitementNomenclaturesImpl implements TraitementNomenclatures {
private static final Logger LOG = LoggerFactory.getLogger(TarificationFactureImpl.class);
#EJB(name = "AccesNomenclatures-interne-ebx")
private transient AccesNomenclatureEBX accesEbx;
#EJB(name = "AccesElementFacturation-interne-ebx")
private transient AccesElementFacturationEBX accesRefEbx;
/*
* (non-Javadoc)
*
* #see
* fr.atom.referentiel.sante.nomenclature.service.TraitementNomenclature#extraireNomenclaturesDesPrestations(java
* .util.List, java.util.Date, fr.atom.configuration.SoapContext)
*/
#Override
public ContenusNomenclatures extraireNomenclaturesDesPrestations(
final List<PrestationDeSante<? extends Identifiant>> pPrestations, final Date pDateTraitement,
final SoapContext pContext) {
.......
}
}

Resources