Spring Data Jpa: save an entity with #ManyToOne - spring-mvc

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.

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

Which component should handle DB access in the Java EE stack with regards to the MVC pattern

I'm fairly new to both Java EE and MVC. I have to develope a web application using Servlet, JSP, JB and EJB. As most applications mine too needs to interact with a RDBMS.
A friend of mine sent me a wep App he developed in which he has a
Serializable DbManager class
in which a
private transient Connection
exists as a member variable.
In all his servlets in which he needs DB access he has a DbManager variable. It is instantiate in the init method of the servlet and it is retrived like this :
this.manager = (DbManager)super.getServletContext().getAttribute("dbmanager");
All the queries are implemented as public methods of the DbManager Class.
I was wondering if this is a good way to implement such needs or if there is a better way to handle Db access and queries execution. I tought of implementing business logic and thus DB access as public methods in my EJBs.
Thanks for any help!
Homemade DbManager style classes are redundant when you are living in a JavaEE environment. You can make use of JPA for performing all your database queries from a stateless session bean that forms the "controller" part of your MVC architecture:
#Stateless
public class OrderController {
#PersistenceContext
private EntityManager em;
public void addNewOrder(Order order) {
em.persist(order)
}
public List<Order> findAllOrders() {
TypedQuery<Order> findAllOrdersQuery = em.createQuery("select o from Order o", Order.class);
return findAllOrdersQuery.list();
// In practice you would add pagination to this.
// It's not practical to return a million orders to your view.
}
...
}
This stateless EJB manages all transactions on your behalf, so you don't normally need to be concerned with beginning, committing and/or rolling back transactions.
The Order class is a component of your "model":
#Entity
public class Order {
#Id
private long id;
#Column
private String orderNumber;
#Column
private String description;
// other attributes
...
Order() { }
public Order(String orderNumber, String description) {
this.orderNumber = orderNumber;
this.description = description;
}
// setters and getters
...
// you must also override equals() and hashCode()
}
You will see many examples where developers introduce a so called DAO layer into their controller, but this is considered redundant as the EntityManager essentially satisfies that contract.

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

How can I use same EJB in two different CDI beans and retrieve the values set from one bean into the another?

I have a stateful session bean where a list is maintained:
#Stateful
public class CartDAO{
private List<ShoppingCart> tempCart;
public void add(ShoppingCart shoppingCart){
tempCart.add(shoppingCart);
}
public List<ShoppingCart> getCart(){
return tempCart;
}
#PostConstruct
public void init(){
tempCart = new ArrayList<>();
}
}
Controller1 to add to the cart:
#Named
#SessionScoped
public class Controller1 implements Serializable {
#EJB
CartDAO cartDao;
public String addToShoppingCart() {
cartDao.add(shoppingCart);
}
}
Now, i want to ask you could i get the added items to the list from another cart?
#Named
#SessionScoped
public class Controller2 implements Serializable {
#EJB
CartDAO cartDao;
public String getShoppingCart() {
System.out.println(cartDao.getCart());//returns null
}
}
Obviously the above code returns null.
How do I retrieve the list from another controller. Any help will be much appreciated.
I don't see any obvious mistake here (are you sure that you don't call Controller2#getShoppingCart() before adding any items do your CartDAO?) but here are couple of my notions
you should have your CartDAO implement some interface or make it #LocalBean
all stateful beans should have method annotated with #Remove so you can clean the resources used in the bean (close datasources and son) and bean will be removed from the memory after this call
now it's recommended to use #Inject everywhere instead of #EJB, it's the same (you have to use #EJB only when you inject remote beans)
And also one point, if the System.out.println(cartDao.getCart()); returns null than it means the #PostConstruct haven't been called which is strange. Can you provide some more info about container and your environment?Also show us imports, this is big source of mistakes.

Hibernate search with lucene for two tables

I have two tables CatalogueBase and CatalogueCopydetails now i am using Hibernate search for CatalogueBase table but i wanted to search even in CatalogueCopydetails table. This two tables are related with #ManyToOne (i.e CatalogueCopydetails using CatalogueBase id as foreign key), hear for one entry of CatalogueBase their will be 'n' numbers of CatalogueCopydetails
CatalogueBase POJO Class
#Indexed
#JsonAutoDetect
#Entity
#Table(name="catalogueBase")
public class CatalogueBase extends BaseObject implements Serializable {
private Long id;
......
#Id
#GeneratedValue
#Column(name="id")
#Field(index = Index.YES, analyze = Analyze.YES, store = Store.YES)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
....
CatalogueCopydetails POJO Class
#JsonAutoDetect
#Entity
#Table(name="cataloguecopydetails")
public class CatalogueCopyDetails extends BaseObject implements Serializable {
private CatalogueBase catalogueBase;
......
#ManyToOne
#JoinColumn(name="cataloguebaseid" , insertable=true, updatable=true,nullable=true)
public CatalogueBase getCatalogueBase() {
return catalogueBase;
}
public void setCatalogueBase(CatalogueBase catalogueBase) {
this.catalogueBase = catalogueBase;
}
......
at least how can i use #IndexedEmbedded for this scenario (i don't think i can use #IndexedEmbedded because CatalogueBase have no relation to CatalogueCopyDetails like OneToOne or OneToMany etc only CatalogueCopyDetails references CatalogueBase )
how can i do this..?, any help will be appreciated, Thanks.
The easiest way would of course be to make the relation bidirectional. Is there a good reason why you don't want to do that? The other thing you could do is to add #Indexed to CatalogueCopyDetails as well and use #IndexedEmbedded on CatalogueBase. You could then write a query using the CatalogueCopyDetails index. Whether this works will depend on your use case and what you actually want as result of query.

Resources