Problem with adding values into my database using JPA - java

I have a function that add into my database (using JPA) a user and his items ,the relationship many-to- many. I have the following tables :
profilUser
item
associationProfileUserItem
on the GUI I enter the login and password of the user and I choose a list of names of items, I have worte a function recuperate id of Item BY their name (to add them to the association).
the problem is that the function insert just the last item choosen for the user and ignore the rest!
My code:
public void addProfilUser()
{
try{
EntityTransaction entr=em.getTransaction();
entr.begin();
AssociationItemProfilPK ItemprofilPk=new AssociationItemProfilPK();
AssociationItemProfil Itemprofil=new AssociationItemProfil();
ProfilUser user=new ProfilUser();
user.setLogin(login);
user.setPassword(password);
em.persist(user);
for (Integer val : getListidItemByItemName())
{
ItemprofilPk.setItemId(val);
ItemprofilPk.setProfilId(user.getProfilUserId());
Itemprofil.setAssociationItemProfilPK(ItemprofilPk);
}
em.persist(Itemprofil);
entr.commit();
}
catch (Exception e )
{
System.out.println(e.getMessage());
System.out.println("Failed");
}
finally {
em.close();
emf.close();
}
}
public ArrayList<Integer> getListidItemByItemName()
{
try{
EntityTransaction entityTrans=emm.getTransaction();
entityTrans.begin();
for (String val : listItem)
{
System.out.println("my values"+val);
javax.persistence.Query multipleSelect= em.createQuery("SELECT i.ItemId FROM Item i WHERE i.ItemName IN (:w)" );
multipleSelect.setParameter("w", val);
List ItemId = new LinkedList();
ItemId= multipleSelect.getResultList();
listIdItem = new ArrayList(ItemId);
}
entityTrans.commit();
System.out.println("Id for given item name"+listIdItem);
return listIdItem;
}
catch(Exception e)
{
e.printStackTrace();
}

There are several problems with your code.
First one: you don't respect naming conventions. variables should start with a lower-case letter. This makes your code harder to read for seasoned Java programmers.
Second one: you loop over your item IDs, and change the value of your ItemprofilPk and Itemprofil objects. But you update always the same objects, and only persist the item after the loop. so, of course, only the last value is persisted. Change to something like this:
for (Integer val : getListidItemByItemName()) {
AssociationItemProfilPK itemprofilPk = new AssociationItemProfilPK();
AssociationItemProfil itemprofil = new AssociationItemProfil();
itemprofilPk.setItemId(val);
itemprofilPk.setProfilId(user.getProfilUserId());
itemprofil.setAssociationItemProfilPK(itemprofilPk);
em.persist(itemprofil);
}
Third one: your mapping is more complex than id needs. You should not have an entity to map the association table. Instead, you should thus have a list of items in the ProfilUser entity, and a list of profilUsers in the Item entity :
public class ProfilUser {
#ManyToMany
#JoinTable(
name = "associationProfileUserItem",
joinColumns = #JoinColumn(name = "PROFIL_ID"),
inverseJoinColumns=#JoinColumn(name="ITEM_ID")
private List<Item> items;
}
public class Item {
#ManyToMany(mappedBy = "items")
private List<ProfilUser profilUsers;
}

Related

Implementation of for loop using java8 features

Can somebody please help me to restructure the following code using java8 features.
Here is my code.
private List<CreateChildItemResponse> createChildItems(String[] childUpcNumbers, String[] childItemNbrs,
ItemVo parentItem, UserVo user, boolean isEnableReverseSyncFlag, Integer parentItemNbr, Long parentUpcNbr,int childUpcNbrsize, ItemManagerDelegate managerDelegate) throws NumberFormatException, ValidationException,ChildNotFoundException, ResourceException, ChildItemException {
List<ItemVo> resultList = new ArrayList<ItemVo>();
List<CreateChildItemAssortmentResponse> relations = null;
CreateChildItemResponse response = new CreateChildItemResponse();
try {
for (int i = 0; i < childUpcNumbers.length; i++) {
// parentItem.setItemNbr(itemNumberList.get(i));
logger.info("-------Item Nbrs-----" + parentItem.getItemNbr());
ItemVo child = createItemForMigration(
populateChildItemVo(parentItem, getGtin(childUpcNumbers[i]), Integer.valueOf(childItemNbrs[i])),
user, isEnableReverseSyncFlag, managerDelegate);// null scales for all except scales integration
resultList.add(child);
}
relations = this.populateAssortmentRelationVo(parentItem.getItemNbr(), resultList);
response = getSuccessResponse(parentItemNbr, relations, parentUpcNbr);
// utx.commit();
} catch (Exception e) {
logger.info("Exception occurs while creating child item", e);
relations = this.populateAssortmentRelationVoForException(e, resultList);
response = getFailureResponseForException(parentItemNbr, relations, parentUpcNbr, e, resultList.size(),
childUpcNbrsize);
finalResponse.add(response);
throw new ChildItemException(e.getMessage(), finalResponse, e);
}
finalResponse.add(response);
return finalResponse;
}
here I am calling the below method in the above code
relations = this.populateAssortmentRelationVo(parentItem.getItemNbr(), resultList);
And the implementation is
private List<CreateChildItemAssortmentResponse> populateAssortmentRelationVo(Integer parentItemNumber,
List<ItemVo> childs) {
List<CreateChildItemAssortmentResponse> relationList = new ArrayList<CreateChildItemAssortmentResponse>();
for (ItemVo child : childs) {
CreateChildItemAssortmentResponse relation = new CreateChildItemAssortmentResponse();
relation.setItemNbr(child.getItemNbr());
relation.setUpcNbr(convertUpcToString(child.getEachGtin().getGtinNbr()));
relation.setStatus("SUCCESS");
relation.setMessage("");
relationList.add(relation);
}
return relationList;
}
Here I want to take a constructor for the populateAssortmentRelationVo() and how to use stream and mapper inside this.
First declare a mapping function:
private CreateChildItemAssortmentResponse> itemVoToResponse(ItemVo item) {
CreateChildItemAssortmentResponse response = new CreateChildItemAssortmentResponse();
response.setItemNbr(item.getItemNbr());
response.setUpcNbr(convertUpcToString(item.getEachGtin().getGtinNbr()));
response.setStatus("SUCCESS");
response.setMessage("");
return relationList;
}
and simply map all the elements of one list into another one:
relations = resultList.stream()
.map(this::itemVoToResponse)
.collect(toList());

Is there a way to return error cause entity?

When the insert or update returns error it returns a long of (-1), is there anyway to return the error entity when inserting same id?
I'm currently using this code :
// Inserting new product
long id = database.productDAO().insert(product);
// Product already exists
if (id == -1) {
Product existingProduct = database.productDAO().select(product.getId());
existingProduct.setInventory(product.getInventory());
if (count > existingProduct.getAllowedMax())
existingProduct.setAllowedMax(count);
database.productDAO().update(existingProduct);
}
#Dao
public interface ProductDAO {
/**
* #return all of products
*/
#Query("SELECT * FROM product")
List<Product> select();
#Insert(onConflict = OnConflictStrategy.IGNORE)
List<Long> insert(Product... products);
#Update(onConflict = OnConflictStrategy.IGNORE)
void update(Product... products);
}
I want to be some way so I can directly find the error entity and make changes so I can get rid of a select query and save some resource, like this :
Product existingProduct = database.productDAO().insert(product);
// Product already exists
if (existingProduct != null){
existingProduct.setInventory(product.getInventory());
if (count > existingProduct.getAllowedMax())
existingProduct.setAllowedMax(count);
database.productDAO().update(existingProduct);}
productDAO().insert method should return the inserted product, and from there you can get the product id.
public Product insert(Product ObjectToAdd){
{
if (DuplicateId){ // use a flag or a try/catch block to know if there is a record with given id already.
return null // or set the id to -1 or some default value :) ObjectToAdd.setId(-1)
}
return ObjectToAdd
}
Remove OnConflictStrategy from the queries. this causes to throw the exception so you can handle it as you wanted.
#Insert
List<Long> insert(Product... products);
Now when you invoke the above method, if room encounters any error at runtime it throws an Exception, you can catch and provide custom error handling logic
try {
long id = database.productDAO().insert(product);
} catch (Exception e) {
// handle it here
}

How to set value for foreign key

I can't set deptID value which is a foreign key I tried many ways, but it doesn't work.
I am getting the values from HTML form.
mapping table units
public BigDecimal getUnitId() {
return this.unitId;
}
public void setUnitId(BigDecimal unitId) {
this.unitId = unitId;
}
public Depts getDepts() { //deptID column - FK
return this.depts;
}
public void setDepts(Depts depts) {
this.depts = depts;
}
my code
<%
SessionFactory sf= new Configuration().configure().buildSessionFactory();
Session s= sf.openSession();
Transaction t= s.beginTransaction();
String unitID= request.getParameter("unitID");
String deptID= request.getParameter("deptID");
String unitName= request.getParameter("unitName");
Units r= new Units(); //this code to set deptID
Depts y= new Depts();
r.setUnitId(new BigDecimal(unitID));
//r.setDepts(y.setDeptId(new BigDecimal(deptID)));//here is my problem
y.setDeptId(new BigDecimal(deptID));
r.setUnitName(unitName);
s.save(r);
t.commit();
out.println("done enserting");
%>
I could suspect the error by looking at your code that you're trying to save the value which you're receiving from your html page, instead of saving the object of your Department (or your class name which has deptID primary-key) class.
In order to save the deptID along with your record :-
you need to get the object of that class first. Something like this :-
Units r = new Units();
YourDepartmentClass d = getDeparmentRecord(id) //get the `YourDepartmentClass` class object on the basis of the id you're receiving
r.setDepId(d); //set/associate YourDepartmentClass object in your Unit's object
//save the record

Spring - in controller I find data from database, but I can't delete these data from database

According to the logic of the application, I have a controller to remove the recycle bin. By the link we get the session id, by it we search for the user in the database and delete all the invoices associated with it.
#RequestMapping(path="/basket/del/{sessId}", method=RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public BasketListReply delAllProducts(#PathVariable String sessId){
BasketListReply rep = new BasketListReply();
try {
//check if session exist
List<Long> delList = userService.findInvoiceBySessionId(sessId);
//delList contain list of invoices id to delete
if(delList != null) {
for(int i=0;i<delList.size();i++){
invoiceService.delInvoice(delList.get(i));
}
}
}catch(Exception e){
rep.retcode = -1;
rep.error_message = e.getMessage();
}
return rep;
}
With method findInvoiceBySessionId() I get list of invoices from collection () to delete.
public List findInvoiceBySessionId(String sessId) throws Exception{
List list = new ArrayList();
List<Appuser> users = findUserBySessionId(sessId);
if(!users.isEmpty()) {
//if exist, then extract invoices for this user
Appuser u = users.get(0);
List<Invoice> invoices = (List<Invoice>)u.getInvoiceCollection();
for(Invoice inv:invoices) {
list.add(inv.getOrderId());
}
}
return list;
}
Method delInvoice() I use to delete invoice from repository.
public void delInvoice(Long orderId){
if(invoiceRepository.findOne(orderId) == null) {
return;
}
invoiceRepository.delete(orderId);
}
File Appuser.java (field that contain collection of Invoices):
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private Collection<Invoice> invoiceCollection;
Did I understand correctly that I can not in one controller and extract data from the database via JPA and delete the same data ... since the deletion should go in a separate transaction.
Or am I doing something wrong?
When I delete the data by redirecting the request to the controller to delete the data, everything works fine.

GAE + JDO : Deleting Child object cause issue in google app engine java

I am using JDO in GAE. I have two JDO classes having one to many relationship. parent class is
#PersistenceCapable(detachable="true")
#FetchGroup(name="childerns", members={#Persistent(name="aliasName")})
public class IdentityProvider {
#PrimaryKey
#Persistent
private String url;
#Persistent
private String domainName;
#Persistent
#Element(dependent = "true")
private ArrayList<AliasDomain> aliasName = new ArrayList<AliasDomain>();
}
The child classes is
#PersistenceCapable(detachable = "true")
public class AliasDomain {
#Persistent
private String url;
#Persistent
private String aliasName;
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
}
I am just performing CURD operations on both entity. First i create the parent instance and then i create the child instance as
public void addAliasDomain(AliasDomain domain) {
String url = domain.getUrl();
PersistenceManager pm = PMFSingleton.get().getPersistenceManager();
IdentityProvider idp = null;
Transaction txn = null;
try {
txn = pm.currentTransaction();
txn.begin();
pm.getFetchPlan().addGroup("childerns");
idp = pm.getObjectById(IdentityProvider.class, url);
idp = pm.detachCopy(idp);
idp.getAliasName().add(domain);
pm.makePersistent(idp);
txn.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if ( txn.isActive() ) {
txn.rollback();
}
pm.close();
}
}
My issue is created when i delete any child instance. As you see from the above function i link the child to the parents( means add child object into arrayList). So when child is deleted its reference in the parents is not deleted so at the detached time of parents object i got exception which is as
Object of type "user.oauth.jdo.model.IdentityProvider" and identity "yahoo.com" was not detached correctly. Please consult the log for any possible information.
org.datanucleus.exceptions.NucleusUserException: Object of type "user.oauth.jdo.model.IdentityProvider" and identity "yahoo.com" was not detached correctly. Please consult the log for any possible information.
at org.datanucleus.state.JDOStateManager.detachCopy(JDOStateManager.java:2942)
at org.datanucleus.ObjectManagerImpl.detachObjectCopy(ObjectManagerImpl.java:2591)
at org.datanucleus.api.jdo.JDOPersistenceManager.jdoDetachCopy(JDOPersistenceManager.java:1145 )
at org.datanucleus.api.jdo.JDOPersistenceManager.detachCopy(JDOPersistenceManager.java:1174)
at user.oauth.data.broker.IDPJDOBroker.retrieveDomainList(IDPJDOBroker.java:49)
The code of function retreiveDomainList in IDPJDOBroker is
public List retrieveDomainList() {
PersistenceManager pm = PMFSingleton.get().getPersistenceManager();
Query query = pm.newQuery(IdentityProvider.class);
List<IdentityProvider> list = null;
List<IdentityProvider> detachedList = null;
IdentityProvider idp = null;
try {
pm.getFetchPlan().addGroup("childerns");
list = (List<IdentityProvider>) query.execute();
detachedList = new ArrayList<IdentityProvider>();
for(IdentityProvider obj : list){
idp = pm.detachCopy(obj);
OAuthJDOBroker broker = new OAuthJDOBroker();
int actUsers = 0;
if ( idp.getHistory() != null && idp.getHistory().size() > 0) {
actUsers = broker.calculateActiveUser(idp.getUserActiveDuration(),idp.getDomainName());
}
idp.setActiveUsers(actUsers);
detachedList.add(idp);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
query.closeAll();
pm.close();
}
return detachedList;
}
Please tell me what to do? Is it not possible in JDO to delete the child? if it is possible then how to do it properly.
I have just seen this, but in case anyone arrives here, to delete a child object in a one to many relationship you must delete the reference from the parent, the child object will be deleted "transparently"

Categories