Join table with column. How is possible? - java

Anybody to know something about this kind of queries:
#Entity
#Table(name="ACCOUNT")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#NamedQueries({
#NamedQuery(name = Account.GET_EXPIRATION_DATE, query="SELECT account.expirationDate FROM " +
"Domain domain JOIN domain.account WHERE domain.id = :domainId"),
#NamedQuery(name = Account.GET_BALANCE, query="SELECT account.balance FROM " +
"Domain domain JOIN domain.account WHERE domain.id = :domainId")
})
I dont understand what is this "Domain domain JOIN domain.account" we can join one table with another but it seams we join table with column .. ?
these are the related classes:
package com.smsoffice.admin;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import static javax.persistence.CascadeType.*;
import com.smsoffice.billing.Account;
import com.smsoffice.billing.PrepaidAccount;
#Entity
#Table(name="DOMAIN")
#NamedQueries({
#NamedQuery(name=Domain.GET_ALL_DOMAINS, query="SELECT d FROM Domain d ORDER BY d.name"),
#NamedQuery(name=Domain.GET_ACCOUNT, query="SELECT d.account FROM Domain d WHERE d.id = :id"),
#NamedQuery(name=Domain.GET_DOMAIN_BY_STATUS, query="SELECT d FROM Domain d WHERE d.enabled = :enabled ORDER BY d.name"),
#NamedQuery(name=Domain.GET_DOMAIN_BY_NAME, query="SELECT d FROM Domain d WHERE d.name = :name")
})
public class Domain implements Serializable {
private static final long serialVersionUID = 1L;
public final static String GET_ALL_DOMAINS = "Domain.getAllDomains";
public final static String GET_ACCOUNT = "Domain.getAccount";
public final static String GET_DOMAIN_BY_STATUS = "Domain.getAllDomainsByStatus";
public final static String GET_DOMAIN_BY_NAME = "Domain.getDomainByName";
public final static transient Domain ROOT = new Domain("ROOT");
public static Domain SYSTEM_DOMAIN = new Domain("SYSTEM");
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(unique = true, length = 96)
private String name;
//unique id of the service - one per domain
#GeneratedValue(strategy = GenerationType.AUTO)
private int serviceId;
//indicates whether the domain is enabled
private Boolean enabled = true;
//short code for the domain sms events
private int shortCode;
//prefix for parsing
private String prefix;
private String clientPrefix = "";
//bank account
#OneToOne(cascade = {PERSIST, REFRESH, REMOVE})
private Account account = new PrepaidAccount();
#OneToMany
private Set<User> users = new HashSet<User>();
public Domain() {}
public Domain(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getServiceId() {
return serviceId;
}
public void setServiceId(int serviceId) {
this.serviceId = serviceId;
}
public int getShortCode() {
return shortCode;
}
public void setShortCode(int shortCode) {
this.shortCode = shortCode;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public Set<User> getUsers() {
return users;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Domain)) {
return false;
}
Domain domain = (Domain) obj;
return getName().toUpperCase().equals(domain.getName().toUpperCase());
}
#Override
public int hashCode() {
return getName().toUpperCase().hashCode();
}
#Override
public String toString() {
return "[" + name + "("+ account + ")]";
}
public int getId() {
return id;
}
public void setClientPrefix(String clientPrefix) {
this.clientPrefix = clientPrefix != null ? clientPrefix : "";
}
public String getClientPrefix() {
return clientPrefix;
}
}
and this one:
package com.smsoffice.billing;
import static javax.persistence.CascadeType.ALL;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name="ACCOUNT")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#NamedQueries({
#NamedQuery(name = Account.GET_EXPIRATION_DATE, query="SELECT account.expirationDate FROM " +
"Domain domain JOIN domain.account account WHERE domain.id = :domainId"),
#NamedQuery(name = Account.GET_BALANCE, query="SELECT account.balance FROM " +
"Domain domain JOIN domain.account account WHERE domain.id = :domainId")
})
public abstract class Account {
public static final MathContext MATH_CONTEXT = new MathContext(9, RoundingMode.HALF_UP);
public static final int SCALE = 3;
public static final int PRECISION = 9;
public static final String GET_BALANCE = "Account.getBalance";
public static final String GET_EXPIRATION_DATE = "Account.getExpirationDate";
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(precision = PRECISION, scale = SCALE)
protected BigDecimal balance = BigDecimal.ZERO;
#OneToOne(cascade = ALL)
protected Tariff tariff;
private Date activationDate = new Date();
private Date expirationDate;
public Account() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, 1);
setExpirationDate(calendar.getTime());
}
public BigDecimal getBalance() {
return balance;
}
public Tariff getTariff() {
return tariff;
}
public void setTariff(Tariff tariff) {
this.tariff = tariff;
}
void deposit(BigDecimal amount) {
balance = balance.add(amount).setScale(SCALE, MATH_CONTEXT.getRoundingMode());
}
abstract boolean hasCredit(int eventCount);
abstract void makePayment(int eventCount) throws PaymentException;
public int getId() {
return id;
}
public Date getActivationDate() {
return activationDate;
}
public void setActivationDate(Date activationDate) {
this.activationDate = normalizeActivationDate(activationDate);
}
void setExpirationDate(Date expirationDate) {
this.expirationDate = normalizeExpirationDate(expirationDate);
}
public Date getExpirationDate() {
return expirationDate;
}
public boolean isExpired() {
Date now = new Date();
return now.after(expirationDate);
}
#Override
public String toString() {
return "[balance: " + balance + "; tariff: " + (tariff != null ? tariff.getPrice() : "no tariff") + "; expiration date: " + expirationDate.toString() + "]";
}
public void setBalance(BigDecimal newBalance) {
this.balance = newBalance;
}
private static final Date normalizeActivationDate(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
private static final Date normalizeExpirationDate(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
}

Well, these are not really SQL queries, but rather JPQL queries - there is a very good tutorial describing this, along with very nice examples. Note that in JPQL you do not work directly with the tables, bur rather with entities of your domain model.
But to your question, let's take this query as an example:
SELECT account.balance FROM Domain domain JOIN domain.account WHERE domain.id = :domainId
SELECT account.balance will return the value of balance attribute of the account that was JOINed to the given domain record
FROM Domain domain says that Domain entity will be used to query the data from related table, defined on the Domain entity using #Table(name="DOMAIN"); the lowercase domain is just an alias to be used within this query (see e.g. the WHERE portion of the query)
JOIN domain.account will be used, together with annotation #OneToOne(cascade = {PERSIST, REFRESH, REMOVE}) defined on the account field of Domain entity, to get the relevant record from the table represented by Account entity
WHERE domain.id = :domainId will limit the results to return only the Domain with the given id, together with its account; the part :domainId is a "query parameter" and is most likely replaced somewhere in the code with an actual value, using code like query.setParameter("domainId", someValue);
So the whole query should return value of BigDecimal type (see field balance defined in Account entity).

Related

getting error 'Invalid Column' in JPA while Fetching data using Join tables

I am getting Invalid Column name error when running my application. Below are attached log and entity and repo class.
When I run Select * query then it works but it does not work when I select certain columns.
select * from reorg_view_x x join resource_hierarchy rh on (rh.resource_id=x.faoi_rid)where not exists (select 1 from resource_hierarchy where resource_name =x.t_aoi)and x.region= :region and trunc (x.reorg_dt) = :reorgDt
I caanot use Select * because I need some column names only for my application. Please stick with JPA only.
ERROR LOG:
Hibernate: select distinct x.t_aoi resourceName, x.faoi_prid parentResourceId, rh.time_zone timeZone, rh.language language, to_date(created_dttm) from reorg_view_x x join resource_hierarchy rh on (rh.resource_id=x.faoi_rid)where not exists (select 1 from resource_hierarchy where resource_name =x.t_aoi)and x.region= ? and trunc (x.reorg_dt) = ?
{"logType":"DEBUG","logLevel":"WARN","logTimestamp":"2021-09-15T12:58:11.696-05:00","logger":"org.hibernate.engine.jdbc.spi.SqlExceptionHelper","label":"SQL Error: 17006, SQLState: 99999","runtime":{"instance":"unknown","clusterName":"unknown","namespace":"unknown","image":"unknown","platformIdentifier":"AJSC7_JERSEY"},"application":{"deploymentUnitName":"com.att.dmp.ReorgResourceCreatorMs","motsApplicationAcronym":"MOTS_ID"}}
{"logType":"DEBUG","logLevel":"ERROR","logTimestamp":"2021-09-15T12:58:11.697-05:00","logger":"org.hibernate.engine.jdbc.spi.SqlExceptionHelper","label":"Invalid column name","runtime":{"instance":"unknown","clusterName":"unknown","namespace":"unknown","image":"unknown","platformIdentifier":"AJSC7_JERSEY"},"application":{"deploymentUnitName":"com.att.dmp.ReorgResourceCreatorMs","motsApplicationAcronym":"MOTS_ID"}}
{"logType":"DEBUG","logLevel":"ERROR","logTimestamp":"2021-09-15T12:58:11.773-05:00","logger":"com.att.dmp.service.RestServiceImpl","label":"Exception in createAoi service:","runtime":{"instance":"unknown","clusterName":"unknown","namespace":"unknown","image":"unknown","platformIdentifier":"AJSC7_JERSEY"},"application":{"deploymentUnitName":"com.att.dmp.ReorgResourceCreatorMs","motsApplicationAcronym":"MOTS_ID"}}
I have entity: ResourceHierarchy but not reorg_view_x
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="resource_hierarchy")
public class ResourceHierarchy {
#Id
#Column(name="RESOURCE_ID", nullable = false)
private String resourceID;
#Column(name="RESOURCE_NAME", nullable = false)
private String resourceName;
#Column(name="PARENT_RESOURCE_ID", nullable = false)
private String parentResourceID;
#Column(name="RESOURCE_TYPE", nullable = false)
private String resourceType;
#Column(name="TIME_ZONE", nullable = false)
private String timeZone;
#Column(name="LANGUAGE", nullable = false)
private String language;
#Column(name="EMAIL_ADDRESS")
private String emailAddress;
#Column(name="ORGANIZATION")
private String organization;
#Column(name="CREATED_BY")
private String createdBy;
#Column(name="CREATED_DTTM", nullable = false)
private Date createdDttm;
#Column(name="LAST_UPDATED_BY")
private String lastUpdatedBy;
#Column(name="LAST_UPDATED_DTTM")
private Date lastUpdatedDttm;
#Column(name="ACTIVE_FLAG")
private String activeFlag;
#Column(name="CAPACITY_TYPE")
private String capacityType;
#Column(name="DWA_FLAG")
private String dwaFlag;
public String getResourceID() {
return resourceID;
}
public void setResourceID(String resourceID) {
this.resourceID = resourceID;
}
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public String getParentResourceID() {
return parentResourceID;
}
public void setParentResourceID(String parentResourceID) {
this.parentResourceID = parentResourceID;
}
public String getResourceType() {
return resourceType;
}
public void setResourceType(String resourceType) {
this.resourceType = resourceType;
}
public String getTimeZone() {
return timeZone;
}
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getOrganization() {
return organization;
}
public void setOrganization(String organization) {
this.organization = organization;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getCreatedDttm() {
return createdDttm;
}
public void setCreatedDttm(Date createdDttm) {
this.createdDttm = createdDttm;
}
public String getLastUpdatedBy() {
return lastUpdatedBy;
}
public void setLastUpdatedBy(String lastUpdatedBy) {
this.lastUpdatedBy = lastUpdatedBy;
}
public Date getLastUpdatedDttm() {
return lastUpdatedDttm;
}
public void setLastUpdatedDttm(Date lastUpdatedDttm) {
this.lastUpdatedDttm = lastUpdatedDttm;
}
public String getActiveFlag() {
return activeFlag;
}
public void setActiveFlag(String activeFlag) {
this.activeFlag = activeFlag;
}
public String getCapacityType() {
return capacityType;
}
public void setCapacityType(String capacityType) {
this.capacityType = capacityType;
}
public String getDwaFlag() {
return dwaFlag;
}
public void setDwaFlag(String dwaFlag) {
this.dwaFlag = dwaFlag;
}
#Override
public String toString() {
return "ResourceHierarchy [resourceID=" + resourceID + ", resourceName=" + resourceName + ", parentResourceID="
+ parentResourceID + ", resourceType=" + resourceType + ", timeZone=" + timeZone + ", language="
+ language + ", emailAddress=" + emailAddress + ", organization=" + organization + ", createdBy="
+ createdBy + ", createdDttm=" + createdDttm + ", lastUpdatedBy=" + lastUpdatedBy + ", lastUpdatedDttm="
+ lastUpdatedDttm + ", activeFlag=" + activeFlag + ", capacityType=" + capacityType + ", dwaFlag="
+ dwaFlag + "]";
}
}
I have ResourceHierarchyRepository like this
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.att.dmp.entity.ResourceHierarchy;
#Repository
public interface ResourceHierarchyRepository extends JpaRepository<ResourceHierarchy, String> {
#Query(value="select distinct x.t_aoi resourceName, x.faoi_prid parentResourceId, rh.time_zone timeZone, rh.language language, to_date(created_dttm) from reorg_view_x x join resource_hierarchy rh on (rh.resource_id=x.faoi_rid)where not exists (select 1 from resource_hierarchy where resource_name =x.t_aoi)and x.region= :region and trunc (x.reorg_dt) = :reorgDt", nativeQuery=true)
List<ResourceHierarchy> findAOI( #Param("reorgDt") String reorgDt,#Param("region") String region);
}
Do I need to create reorg_view_x entity as well and then fetch records in reorgViewX repository instead of doing them in ResourceHierarchy? But I think there are some other easy solutions.
JPA cannot convert few selected columns to entities directly. Now here you have two options:
If you can write your query in JPQL, then you can use the constructor to build your object with few selected fields. Below is the minimal example:
#Query("SELECT new ResourceHierarchy(fieldOne, fieldTwo) FROM ResourceHierarchy WHERE ... ")
public List<ResourceHierarchy> method(String params, ..);
If you want to stick with the native query, then you must change the return type of repository method to List<Map<String, Object>>.

why result not getting in spring data application

I am newbie to spring and java,
I have a case, where i am trying to fetching rows from the mysql table
This is my Controller:
#RequestMapping(value = "/pharmacy/order/dates", method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
public PharmacyOrderDateResponse orderDates(#Valid #RequestBody PharmacyOrderDateRequest request) {
List<PrescriptionOrder> pharmacyOrders = prescriptionOrderService.orderDatesByPharmacyId(request.getPharmacyId(), request.getOrderStatus(), true);
if(pharmacyOrders.size() == 0) {
throw new EntityNotFoundException("No pharmacy orders found");
}
PharmacyOrderDateResponse response = new PharmacyOrderDateResponse();
Set<Date> orderDateSet = new HashSet<>();
for(PrescriptionOrder pharmacyOrder : pharmacyOrders) {
//orderDateSet.add(longToDate(pharmacyOrder.getCreatedAt().getTime()));
}
response.setPharmacyId(pharmacyOrders.get(0).getPharmacyId());
response.setStatus(ResponseStatusCode.SUCCESS);
response.setPharmacyOrderDateDetails(orderDateSet);
response.setTotalDates(orderDateSet.size());
return response;
}
The above controller is used to call the service by the function, so that to get the list of prescription orders.
This is my Service:
package com.axonytes.corporate.service;
import java.util.Date;
import java.util.List;
import com.axonytes.corporate.entity.PrescriptionOrder;
public interface PrescriptionOrderService {
List<PrescriptionOrder> orderDatesByPharmacyId(Long labId, String orderStatus, Boolean status);
}
This is my ServiceImpl:
#Service
#Transactional(readOnly = true)
public class PrescriptionOrderServiceImpl implements PrescriptionOrderService {
private PrescriptionOrderRepository prescriptionOrderRepository;
#Autowired
public PrescriptionOrderServiceImpl(PrescriptionOrderRepository prescriptionOrderRepository) {
this.prescriptionOrderRepository = prescriptionOrderRepository;
}
#Override
public List<PrescriptionOrder> orderDatesByPharmacyId(Long pharmacyId, String orderStatus, Boolean status) {
OrderStatusEnum orderStatusEnum = OrderStatusEnum.fromString(orderStatus);
List<PrescriptionOrder> prescriptionOrder = prescriptionOrderRepository
.findByPharmacyIdAndOrderStatus(pharmacyId, orderStatusEnum.getStatus());
return prescriptionOrder;
}
}
The above service is a implementation function to list the orders, where it calls the repository function.
This is my Repository:
package com.axonytes.corporate.repository;
import java.util.Date;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.axonytes.corporate.entity.PrescriptionOrder;
#Repository
public interface PrescriptionOrderRepository extends JpaRepository<PrescriptionOrder, Long>{
//#Query(value = "select * from PrescriptionOrder po WHERE po.pharmacyId = :pharmacyId AND po.orderStatus = :orderStatus AND po.active = :active ORDER BY po.createdAt ASC")
//List<PrescriptionOrder> findByPharmacyIdAndOrderStatus(#Param("pharmacyId") Long pharmacyId, #Param("orderStatus") int orderStatus, #Param("active") Boolean active);
List<PrescriptionOrder> findByPharmacyIdAndOrderStatus(#Param("pharmacyId") Long pharmacyId, #Param("orderStatus") int orderStatus);
}
This is my Entity:
package com.axonytes.corporate.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
#Entity
#DynamicInsert
#DynamicUpdate
#Table(name = "prescription_orders")
public class PrescriptionOrder extends BaseEntity {
private static final long serialVersionUID = -3853355500806579362L;
#Column(name = "prescription_id")
private Long prescriptionId;
#Column(name = "pharmacy_id")
private Long pharmacyId;
#Column(name = "order_status")
private int orderStatus;
public Long getPrescriptionId() {
return prescriptionId;
}
public void setPrescriptionId(Long prescriptionId) {
this.prescriptionId = prescriptionId;
}
public Long getPharmacyId() {
return pharmacyId;
}
public void setPharmacyId(Long pharmacyId) {
this.pharmacyId = pharmacyId;
}
public int getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(int orderStatus) {
this.orderStatus = orderStatus;
}
}
This ismy OrderStatusEnumClass:
package com.axonytes.corporate.util;
public enum OrderStatusEnum {
PENDING(0, "pending"), DESPATCHED(1, "dispatched");
private int status;
private String name;
OrderStatusEnum(int status, String name) {
this.status = status;
this.name = name;
}
public static OrderStatusEnum fromString(String name) {
if(name != null) {
for(OrderStatusEnum orderStatusEnum : OrderStatusEnum.values()) {
if(name.equalsIgnoreCase(orderStatusEnum.toString())) {
return orderStatusEnum;
}
}
}
return null;
}
#Override
public String toString() {
return name;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
I have row values in the mysql:
id prescription_id pharmacy_id order_Status is_active
1 1 6 0 1
I am trying to list a orders by the following api.
http://localhost:8080/pharmacy/order/dates
POST METHOD with JSON VALUE:
{
"pharmacyId":"6",
"orderStatus":"pending"
}
Eventhough i am having 1 rows in the mysql db table, Output i am getting is:
{
"status": "FAILURE",
"errorCode": 0,
"errorMessage": "No pharmacy orders found"
}
Here you are using spring data and name method resolving. So is spring who translate the name of your method with each property in your entity, in that case you don't have to declare any parameter name so change your method to this:
#Repository
public interface PrescriptionOrderRepository extends JpaRepository<PrescriptionOrder, Long>{
List<PrescriptionOrder> findByPharmacyIdAndOrderStatus(Long pharmacyId, int orderStatus);
}
Note: You have an enum OrderStatusEnum but you are saving into the database an integer, I highly recommend you to modify the object to store and change the int for the enum, would be easier to read

how does ".merge(entity)" work?

i'm creating a java EE (web) application using JPA and EJB for model-tier.
i think i have to use Session Beans for CRUD.
this is my BrandFacade.java (session bean)
package model.business;
import model.localinterface.BrandFacadeLocal;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import model.entities.Brand;
#Stateless
public class BrandFacade extends AbstractFacade<Brand> implements BrandFacadeLocal, BrandFacadeRemote {
#PersistenceContext(unitName = "MyWheelEE-ejbPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public BrandFacade() {
super(Brand.class);
}
#Override
public boolean CreateBrand(String name) {
Brand brand=new Brand(0, name);
boolean result=true;
try {
em.persist(brand);
} catch (Exception e) {
result=false;
}
em.close();
return result;
}
#Override
public void deleteBrand(int brandOid) {
em.remove(getBrandByOid(brandOid));
em.flush();
}
#Override
public Brand getBrandByOid(int brandOid) {
em.flush();
return em.find(Brand.class, brandOid);
}
#Override
public void editBrand(Brand brand) {
em.merge(brand);
em.flush();
}
}
and this is my Brand.java class (entity)
package model.entities;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#Entity
#Table(name = "brand")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Brand.findAll", query = "SELECT b FROM Brand b"),
#NamedQuery(name = "Brand.findByOid", query = "SELECT b FROM Brand b WHERE b.oid = :oid"),
#NamedQuery(name = "Brand.findByName", query = "SELECT b FROM Brand b WHERE b.name = :name")})
public class Brand implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "oid")
private Integer oid;
#Basic(optional = false)
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "brandOid")
private List<Wheelchair> wheelchairList;
public Brand() {
}
public Brand(Integer oid) {
this.oid = oid;
}
public Brand(Integer oid, String name) {
this.oid = oid;
this.name = name;
}
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlTransient
public List<Wheelchair> getWheelchairList() {
return wheelchairList;
}
public void setWheelchairList(List<Wheelchair> wheelchairList) {
this.wheelchairList = wheelchairList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (oid != null ? oid.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Brand)) {
return false;
}
Brand other = (Brand) object;
if ((this.oid == null && other.oid != null) || (this.oid != null && !this.oid.equals(other.oid))) {
return false;
}
return true;
}
#Override
public String toString() {
return "model.entities.Brand[ oid=" + oid + " ]";
}
}
i wish to know how does .merge method work... i think it search in the DB the entity which has the primary key of the entity passed and then it works on edited fields right?
but how i can edit a brand knowing only the name?
It's quite simple really, here your answers:
I wish to know how does .merge method work...
When you call merge method, JPA will verify if the field marked as primary key (#Id) is not null:
- IF YES: JPA will create a new record in your database
- IT NOT: JPA will update your record using the id field value, something like (UPDATE table_name ..... WHERE id=?)
So, you are right :)
but how i can edit a brand knowing only the name?
If you wanna edit a record knowing another field rather than Id field, you will have 2 options:
1. Write JPQL, something like:
UPDATE Person p SET p.lastName = 'New Last Name' WHERE p.name = 'his name'
Write a Native Query, in this case, you will write PLAIN SQL and the run it
In both cases, you will need to do something like:
Query query = em.createQuery or em.createNativeQuery
and then just execute it

Java persistence: named queries. Multiple parameters changes boolean values to int?

I'm an amateur programmer and I'm having trouble with the java eclipse persistence named queries. I have an entity class. In this class I have created named queries. With the ClientInformation.getList I have two parameters. One on active (Boolean) and one on type (int). When I remove either one it works like a charm, but when I try them both it transforms the boolean value to an integer.
Entity class
package datamodel;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "CLIENT_INFORMATION")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "ClientInformation.getList", query =
"SELECT c.ciName FROM ClientInformation c WHERE "
+ "(c.ciActive = true or c.ciActive = :ciActive) AND "
+ "(:ciType = 0 OR c.ciType = :ciType)"),
#NamedQuery(name = "ClientInformation.getID", query = "SELECT c.ciId FROM ClientInformation c WHERE c.ciName like :ciName"),
#NamedQuery(name = "ClientInformation.findAll", query = "SELECT c FROM ClientInformation c"),
#NamedQuery(name = "ClientInformation.findByCiId", query = "SELECT c FROM ClientInformation c WHERE c.ciId = :ciId"),
#NamedQuery(name = "ClientInformation.findByCiType", query = "SELECT c FROM ClientInformation c WHERE c.ciType = :ciType")})
public class ClientInformation implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "CI_ID")
private Integer ciId;
#Lob
#Column(name = "CI_NAME", unique=true)
private String ciName;
#Lob
#Column(name = "CI_ADDRESS")
private String ciAddress;
#Lob
#Column(name = "CI_AREACODE")
private String ciAreacode;
#Lob
#Column(name = "CI_CITY")
private String ciCity;
#Lob
#Column(name = "CI_PHONE")
private String ciPhone;
#Lob
#Column(name = "CI_PHONE2")
private String ciPhone2;
#Lob
#Column(name = "CI_EMAIL")
private String ciEmail;
#Column(name = "CI_ACTIVE")
private Boolean ciActive;
#Lob
#Column(name = "CI_NOTE")
private String ciNote;
#Column(name = "CI_TYPE")
private Integer ciType;
public ClientInformation() {
}
public ClientInformation(Integer ciId) {
this.ciId = ciId;
}
public Integer getCiId() {
return ciId;
}
public void setCiId(Integer ciId) {
this.ciId = ciId;
}
public String getCiName() {
return ciName;
}
public void setCiName(String ciName) {
this.ciName = ciName;
}
public String getCiAddress() {
return ciAddress;
}
public void setCiAddress(String ciAddress) {
this.ciAddress = ciAddress;
}
public String getCiAreacode() {
return ciAreacode;
}
public void setCiAreacode(String ciAreacode) {
this.ciAreacode = ciAreacode;
}
public String getCiCity() {
return ciCity;
}
public void setCiCity(String ciCity) {
this.ciCity = ciCity;
}
public String getCiPhone() {
return ciPhone;
}
public void setCiPhone(String ciPhone) {
this.ciPhone = ciPhone;
}
public String getCiPhone2() {
return ciPhone2;
}
public void setCiPhone2(String ciPhone2) {
this.ciPhone2 = ciPhone2;
}
public String getCiEmail() {
return ciEmail;
}
public void setCiEmail(String ciEmail) {
this.ciEmail = ciEmail;
}
public Boolean getCiActive() {
return ciActive;
}
public void setCiActive(Boolean ciActive) {
this.ciActive = ciActive;
}
public String getCiNote() {
return ciNote;
}
public void setCiNote(String ciNote) {
this.ciNote = ciNote;
}
public Integer getCiType() {
return ciType;
}
public void setCiType(Integer ciType) {
this.ciType = ciType;
}
#Override
public int hashCode() {
int hash = 0;
hash += (ciId != null ? ciId.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof ClientInformation)) {
return false;
}
ClientInformation other = (ClientInformation) object;
if ((this.ciId == null && other.ciId != null) || (this.ciId != null && !this.ciId.equals(other.ciId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "manager.ClientInformation[ ciId=" + ciId + " ]";
}
}
Code snip where I call the named query.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ManagerPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
List clientList = em.createNamedQuery("ClientInformation.getList")
.setParameter("ciActive", this.inactiveClientSelected)
.setParameter("ciType", this.typeClientSelected)
.getResultList();
clientList_ComboBox.addItem("Kies klant...");
if (clientList.isEmpty() == false) {
for (Object clientList1 : clientList) {
clientList_ComboBox.addItem(clientList1);
}
}
em.close();
emf.close();
This is the message I'm getting.
Call: SELECT CI_NAME FROM CLIENT_INFORMATION WHERE (((CI_ACTIVE = 1)
OR (CI_ACTIVE = 1)) AND ((0 = 0) OR (CI_TYPE = 0))) Internal
Exception: java.sql.SQLSyntaxErrorException: Comparisons between
'BOOLEAN' and 'INTEGER' are not supported. Types must be comparable.
String types must also have matching collation. If collation does not
match, a possible solution is to cast operands to force them to the
default collation (e.g. SELECT tablename FROM sys.systables WHERE
CAST(tablename AS VARCHAR(128)) = 'T1') Query:
ReportQuery(name="ClientInformation.getList"
referenceClass=ClientInformation sql="SELECT CI_NAME FROM
CLIENT_INFORMATION WHERE (((CI_ACTIVE = ?) OR (CI_ACTIVE = ?)) AND ((?
= ?) OR (CI_TYPE = ?)))") Error Code: 30000 Call: SELECT CI_NAME FROM CLIENT_INFORMATION WHERE (((CI_ACTIVE = 1) OR (CI_ACTIVE = 1)) AND ((0
= 0) OR (CI_TYPE = 0))) Query: ReportQuery(name="ClientInformation.getList"
referenceClass=ClientInformation sql="SELECT CI_NAME FROM
CLIENT_INFORMATION WHERE (((CI_ACTIVE = ?) OR (CI_ACTIVE = ?)) AND ((?
= ?) OR (CI_TYPE = ?)))")
Any suggestions or do I need to give more information?
Edit: When I remove the last part from the query ("... AND (:ciType = ...etc) the query works fine, so I think I ruled out the actual parameter passing/ the code passes a boolean. Also, when I remove the first parameter (the Boolean) it works as well. So It's (the combination of) the two parameters.

JPA how to update existing object data without exception? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I try to update existing data rows in database but i get that exception:
[EL Warning]: 2012-10-24 20:02:27.798--UnitOfWork(22664464)--Exception [EclipseLink-4002] (Eclipse Persistence Services -
2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '20-http://www.vilpra.lt/products/Foto/Aremikas/Katilas_zvake_big' for key 'PRIMARY' Error Code: 1062 Call: INSERT INTO x_links_media (image, link_id) VALUES (?, ?) bind => [2 parameters bound] Query: InsertObjectQuery(database.entity.XLinksMedia[ xLinksMediaPK=database.entity.XLinksMediaPK[ linkId=20, image=http://www.link.lt/products.jpg ] ])
The main object class is look like code below. There is some variables with relation OneToMany.
package database.entity;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "x_parser_links")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "XParserLinks.findAll", query = "SELECT x FROM XParserLinks x"),
#NamedQuery(name = "XParserLinks.findByLinkId", query = "SELECT x FROM XParserLinks x WHERE x.linkId = :linkId"),
#NamedQuery(name = "XParserLinks.findByPageId", query = "SELECT x FROM XParserLinks x WHERE x.pageId = :pageId"),
#NamedQuery(name = "XParserLinks.findByLink", query = "SELECT x FROM XParserLinks x WHERE x.link = :link"),
#NamedQuery(name = "XParserLinks.findByLevel", query = "SELECT x FROM XParserLinks x WHERE x.level = :level"),
#NamedQuery(name = "XParserLinks.findByLinkType", query = "SELECT x FROM XParserLinks x WHERE x.linkType = :linkType"),
#NamedQuery(name = "XParserLinks.findByCreateDate", query = "SELECT x FROM XParserLinks x WHERE x.createDate = :createDate"),
#NamedQuery(name = "XParserLinks.findByDelDate", query = "SELECT x FROM XParserLinks x WHERE x.delDate = :delDate")})
public class XParserLinks implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "link_id")
private Integer linkId;
#Column(name = "page_id")
private Integer pageId;
#Column(name = "link")
private String link;
#Column(name = "level")
private Integer level;
#Column(name = "link_type")
private Short linkType;
#Column(name = "create_date")
#Temporal(TemporalType.TIMESTAMP)
private Date createDate;
#Column(name = "del_date")
#Temporal(TemporalType.TIMESTAMP)
private Date delDate;
#JoinColumn(name = "tev_link_id")
#OneToOne(cascade = CascadeType.ALL)
private XParserLinks tevas;
#OneToMany(mappedBy = "xParserLink", targetEntity = XLinksMedia.class, cascade = CascadeType.ALL)
private List<XLinksMedia> fotos;
#OneToMany(mappedBy = "xParserLink", targetEntity = XLinksVarchar.class, cascade = CascadeType.ALL)
private List<XLinksVarchar> atributes;
public XParserLinks() {
}
public XParserLinks(Integer linkId) {
this.linkId = linkId;
}
public Integer getLinkId() {
return linkId;
}
public void setLinkId(Integer linkId) {
this.linkId = linkId;
}
public Integer getPageId() {
return pageId;
}
public void setPageId(Integer pageId) {
this.pageId = pageId;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public Short getLinkType() {
return linkType;
}
public void setLinkType(Short linkType) {
this.linkType = linkType;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getDelDate() {
return delDate;
}
public void setDelDate(Date delDate) {
this.delDate = delDate;
}
public XParserLinks getTevas() {
return tevas;
}
public void setTevas(XParserLinks tevas) {
this.tevas = tevas;
}
public List<XLinksMedia> getFotos() {
return fotos;
}
public void setFotos(List<XLinksMedia> fotos) {
this.fotos = fotos;
}
public List<XLinksVarchar> getAtributes() {
return atributes;
}
public void setAtributes(List<XLinksVarchar> atributes) {
this.atributes = atributes;
}
#Override
public int hashCode() {
int hash = 0;
hash += (linkId != null ? linkId.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof XParserLinks)) {
return false;
}
XParserLinks other = (XParserLinks) object;
if ((this.linkId == null && other.linkId != null) || (this.linkId != null && !this.linkId.equals(other.linkId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "database.entity.XParserLinks[ linkId=" + linkId + " ]";
}
}
And here is code where I want to proceed data. XParserLinks object is the man object like code above. In this example I check if object do not have his primary key LinkId then create new object with persist, but else just update object and his values, but I get exception like I mean before when I want to update existing object.
XParserLinks e = entry.getValue();
if (e.getLinkId() == null) {
try {
TarpineManager.startTransaction();
TarpineManager.persist(e);
TarpineManager.commitTransaction();
} catch (Exception ex) {
ex.printStackTrace();
if (TarpineManager.getInstance().getTransaction().isActive()) {
TarpineManager.rollbackTransaction();
}
}
} else {
try {
TarpineManager.startTransaction();
TarpineManager.commitTransaction();
} catch (Exception ex) {
ex.printStackTrace();
if (TarpineManager.getInstance().getTransaction().isActive()) {
TarpineManager.rollbackTransaction();
}
}
}
Are you, by any chance, creating your entity and setting its Id by force? I see your class has a setLinkId(Integer linkId) method on it.
First of all, you should be using merge instead of persist. Now, whit this in mind, the exception is also being thrown by the merge method because JPA can't define if the entity you want to persist is a new one or it's a previosuly fetched one, because the states in the lifecycle aren't the same.
If you create an object and set its id, that entity has the state new, but if you fetched the entity before it should have a detached state. When merged, a detached entity will be correctly updated but a new entity will be persisted and, since the id is taken, the exception is thrown.
You have the entity's ID, so you better fetch them before, update the object and then merge them.

Categories