I want to display distinct year in combo box in ascending order. But the output in combox appears to be repetitive, repetitive in the sense that it shows all the elements of the column of database but i want to show only the distinct data of the column . What am i doing wrong?? I have simply done simple database query before in php. I know it is simply but i am not being to address the query in right order, i guess.
My code is as follows.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package my_ui;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
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.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
*
* #author enjal
*/
#Entity
#Table(name = "production", catalog = "data2", schema = "")
#NamedQueries({
#NamedQuery(name = "Production.findAll", query = "SELECT p FROM Production p"),
#NamedQuery(name = "Production.findByProductionId", query = "SELECT p FROM Production p WHERE p.productionId = :productionId"),
#NamedQuery(name = "Production.findByCropId", query = "SELECT p FROM Production p WHERE p.cropId = :cropId"),
#NamedQuery(name = "Production.findByLocationId", query = "SELECT p FROM Production p WHERE p.locationId = :locationId"),
#NamedQuery(name = "Production.findByArea", query = "SELECT p FROM Production p WHERE p.area = :area"),
#NamedQuery(name = "Production.findByProductionAmount", query = "SELECT p FROM Production p WHERE p.productionAmount = :productionAmount"),
#NamedQuery(name = "Production.findByYieldAmount", query = "SELECT p FROM Production p WHERE p.yieldAmount = :yieldAmount"),
#NamedQuery(name = "Production.findByYearOfProduction", query = "SELECT DISTINCT p FROM Production p WHERE p.yearOfProduction = :yearOfProduction ORDER BY p.yearOfProduction ASC" )})
//SELECT DISTINCT year_of_production FROM `production` ORDER BY year_of_production ASC
public class Production implements Serializable {
#Transient
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "production_id")
private Integer productionId;
#Basic(optional = false)
#Column(name = "crop_id")
private int cropId;
#Basic(optional = false)
#Column(name = "location_id")
private String locationId;
#Basic(optional = false)
#Column(name = "area")
private double area;
#Basic(optional = false)
#Column(name = "production_amount")
private String productionAmount;
#Basic(optional = false)
#Column(name = "yield_amount")
private double yieldAmount;
#Basic(optional = false)
#Column(name = "year_of_production")
private String yearOfProduction;
public Production() {
}
public Production(Integer productionId) {
this.productionId = productionId;
}
public Production(Integer productionId, int cropId, String locationId, double area, String productionAmount, double yieldAmount, String yearOfProduction) {
this.productionId = productionId;
this.cropId = cropId;
this.locationId = locationId;
this.area = area;
this.productionAmount = productionAmount;
this.yieldAmount = yieldAmount;
this.yearOfProduction = yearOfProduction;
}
public Integer getProductionId() {
return productionId;
}
public void setProductionId(Integer productionId) {
Integer oldProductionId = this.productionId;
this.productionId = productionId;
changeSupport.firePropertyChange("productionId", oldProductionId, productionId);
}
public int getCropId() {
return cropId;
}
public void setCropId(int cropId) {
int oldCropId = this.cropId;
this.cropId = cropId;
changeSupport.firePropertyChange("cropId", oldCropId, cropId);
}
public String getLocationId() {
return locationId;
}
public void setLocationId(String locationId) {
String oldLocationId = this.locationId;
this.locationId = locationId;
changeSupport.firePropertyChange("locationId", oldLocationId, locationId);
}
public double getArea() {
return area;
}
public void setArea(double area) {
double oldArea = this.area;
this.area = area;
changeSupport.firePropertyChange("area", oldArea, area);
}
public String getProductionAmount() {
return productionAmount;
}
public void setProductionAmount(String productionAmount) {
String oldProductionAmount = this.productionAmount;
this.productionAmount = productionAmount;
changeSupport.firePropertyChange("productionAmount", oldProductionAmount, productionAmount);
}
public double getYieldAmount() {
return yieldAmount;
}
public void setYieldAmount(double yieldAmount) {
double oldYieldAmount = this.yieldAmount;
this.yieldAmount = yieldAmount;
changeSupport.firePropertyChange("yieldAmount", oldYieldAmount, yieldAmount);
}
public String getYearOfProduction() {
return yearOfProduction;
}
public void setYearOfProduction(String yearOfProduction) {
String oldYearOfProduction = this.yearOfProduction;
this.yearOfProduction = yearOfProduction;
changeSupport.firePropertyChange("yearOfProduction", oldYearOfProduction, yearOfProduction);
}
#Override
public int hashCode() {
int hash = 0;
hash += (productionId != null ? productionId.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 Production)) {
return false;
}
Production other = (Production) object;
if ((this.productionId == null && other.productionId != null) || (this.productionId != null && !this.productionId.equals(other.productionId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "my_ui.Production[ productionId=" + yearOfProduction + " ]";
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
changeSupport.removePropertyChangeListener(listener);
}
}
I want to display distinct year in combo box in ascending order. But the output in combobox appears to be repetitive, repetitive in the sense that it shows all the elements of the column of database but i want to show only the distinct data of the column
And you say this is the query you are using to accomplish that
#NamedQuery(name = "Production.findByYearOfProduction",
query = "SELECT DISTINCT p FROM Production p
WHERE p.yearOfProduction = :yearOfProduction
ORDER Bp.yearOfProduction ASC" )})
The problem with this query is that it's used to find a list Production entities by the yearOfProduction. So say you use this query with the year 1990. That means that any Production entity that was produced in 1990 with be part of the result set. So the only year of production you will see is 1990.
What you want is just the distinct values in a single column, where the actual Production entity is not necessarily concerned. So your query should look more like
SELECT DISTINCT p.yearOfProduction
FROM Production p
ORDER BY p.yearOfProduction ASC
The return value should be a list of just the distinct years, and having no connection to the Production entity. You may want to do some refactoring to your code, where calling this query will return a List<String>. And that's the list you want to use for your combo box, not a List<Production>. Where should you do this refactoring? I can't tell, as you haven't provided the code where you call this query.
Note: So what you should do is create a separate #NamedQuery, and the one you currently have, I think you want to keep for maybe a different combo box maybe, where after a year is selected from the first combo box, the second one is populate with all Production entities for that year. Also note your toString just lists the year of production. So if you want some other representation of the Production entity in a the second combo box, you should change that also.
Also keep in mind when you auto-create an entity in Netbeans, It will create a findAll query and a query findByXxx query for each property of the entity. That's it. All the queries are meant to return a list of Production entities using one that property as the parameter for finding matching results. Any other return types you want (in this case a list of strings) or different parameter queries, you need to create a customized query
Related
I'm using EclipseLink to run some Native SQL. I need to return the data into a POJO. I followed the instructions at EclipseLink Docs, but I receive the error Missing descriptor for [Class]
The query columns have been named to match the member variables of the POJO. Do I need to do some additional mapping?
POJO:
public class AnnouncementRecipientsFlattenedDTO {
private BigDecimal announcementId;
private String recipientAddress;
private String type;
public AnnouncementRecipientsFlattenedDTO() {
super();
}
public AnnouncementRecipientsFlattenedDTO(BigDecimal announcementId, String recipientAddress, String type) {
super();
this.announcementId = announcementId;
this.recipientAddress = recipientAddress;
this.type = type;
}
... Getters/Setters
Entity Manager call:
public List<AnnouncementRecipientsFlattenedDTO> getNormalizedRecipientsForAnnouncement(int announcementId) {
Query query = em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT, AnnouncementRecipientsFlattenedDTO.class);
query.setParameter(1, announcementId);
return query.getResultList();
}
I found out you can put the results of a Native Query execution into a List of Arrays that hold Objects. Then one can iterate over the list and Array elements and build the desired Entity objects.
List<Object[]> rawResultList;
Query query =
em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT);
rawResultList = query.getResultList();
for (Object[] resultElement : rawResultList) {
AnnouncementDeliveryLog adl = new AnnouncementDeliveryLog(getAnnouncementById(announcementId), (String)resultElement[1], (String)resultElement[2], "TO_SEND");
persistAnnouncementDeliveryLog(adl);
}
You can only use native SQL queries with a class if the class is mapped. You need to define the AnnouncementRecipientsFlattenedDTO class as an #Entity.
Otherwise just create the native query with only the SQL and get an array of the data back and construct your DTO yourself using the data.
Old question but may be following solution will help someone else.
Suppose you want to return a list of columns, data type and data length for a given table in Oracle. I have written below a native sample query for this:
private static final String TABLE_COLUMNS = "select utc.COLUMN_NAME, utc.DATA_TYPE, utc.DATA_LENGTH "
+ "from user_tab_columns utc "
+ "where utc.table_name = ? "
+ "order by utc.column_name asc";
Now the requirement is to construct a list of POJO from the result of above query.
Define TableColumn entity class as below:
#Entity
public class TableColumn implements Serializable {
#Id
#Column(name = "COLUMN_NAME")
private String columnName;
#Column(name = "DATA_TYPE")
private String dataType;
#Column(name = "DATA_LENGTH")
private int dataLength;
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public int getDataLength() {
return dataLength;
}
public void setDataLength(int dataLength) {
this.dataLength = dataLength;
}
public TableColumn(String columnName, String dataType, int dataLength) {
this.columnName = columnName;
this.dataType = dataType;
this.dataLength = dataLength;
}
public TableColumn(String columnName) {
this.columnName = columnName;
}
public TableColumn() {
}
#Override
public int hashCode() {
int hash = 0;
hash += (columnName != null ? columnName.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
if (!(object instanceof TableColumn)) {
return false;
}
TableColumn other = (TableColumn) object;
if ((this.columnName == null && other.columnName != null) || (this.columnName != null && !this.columnName.equals(other.columnName))) {
return false;
}
return true;
}
#Override
public String toString() {
return getColumnName();
}
}
Now we are ready to construct a list of POJO. Use the sample code below to construct get your result as List of POJOs.
public List<TableColumn> findTableColumns(String table) {
List<TableColumn> listTables = new ArrayList<>();
EntityManager em = emf.createEntityManager();
Query q = em.createNativeQuery(TABLE_COLUMNS, TableColumn.class).setParameter(1, table);
listTables = q.getResultList();
em.close();
return listTables;
}
Also, don't forget to add in your POJO class in persistence.xml! It can be easy to overlook if you are used to your IDE managing that file for you.
Had the same kind of problem where I wanted to return a List of POJOs, and really just POJOs (call it DTO if you want) and not #Entity annotated Objects.
class PojoExample {
String name;
#Enumerated(EnumType.STRING)
SomeEnum type;
public PojoExample(String name, SomeEnum type) {
this.name = name;
this.type = type;
}
}
With the following Query:
String query = "SELECT b.name, a.newtype as type FROM tablea a, tableb b where a.tableb_id = b_id";
Query query = getEntityManager().createNativeQuery(query, "PojoExample");
#SuppressWarnings("unchecked")
List<PojoExample> data = query.getResultList();
Creates the PojoExample from the database without the need for an Entity annotation on PojoExample. You can find the method call in the Oracle Docs here.
edit:
As it turns out you have to use #SqlResultSetMapping for this to work, otherwise your query.getResultList() returns a List of Object.
#SqlResultSetMapping(name = "PojoExample",
classes = #ConstructorResult(columns = {
#ColumnResult(name = "name", type = String.class),
#ColumnResult(name = "type", type = String.class)
},
targetClass = PojoExample.class)
)
Just put this anywhere under your #Entity annotation (so in this example either in tablea or tableb because PojoExample has no #Entity annotation)
I'm new to Hibernate/JPA. I wrote a simple demo project to start understanding the technology. I have this problem: everything works fine but filtering the persistence object on table primary key field. Every other field can be used to filter the objects without any problem even when I use multiple filters.
This is the simple demo code I wrote:
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<BaRoles> criteriaQuery = criteriaBuilder.createQuery(BaRoles.class);
Root<BaRoles> root = criteriaQuery.from(BaRoles.class);
criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("rocode"), 78));
//criteriaQuery.select(root).where(criteriaBuilder.equal(root.get("rodescri"), "xxxxxxxx")); <-- Works fine
Query<BaRoles> query = session.createQuery(criteriaQuery);
List<BaRoles> roles = query.getResultList(); // <-- Returns nothing filtering rocode, correctly returns obejcts when filtering rodescri
for (int roleCounter = 0; roleCounter < roles.size(); roleCounter++) {
BaRoles role = (BaRoles) roles.get(roleCounter);
}
This is the complete stack trace:
java.lang.NullPointerException
at org.hibernate.query.sqm.sql.internal.BasicValuedPathInterpretation.from(BasicValuedPathInterpretation.java:50)
at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitBasicValuedPath(BaseSqmToSqlAstConverter.java:747)
at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitBasicValuedPath(BaseSqmToSqlAstConverter.java:158)
at org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath.accept(SqmBasicValuedSimplePath.java:87)
at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitComparisonPredicate(BaseSqmToSqlAstConverter.java:1545)
at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitComparisonPredicate(BaseSqmToSqlAstConverter.java:158)
at org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate.accept(SqmComparisonPredicate.java:67)
at org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter.visitQuerySpec(BaseSqmToSqlAstConverter.java:364)
at org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator.visitSelectStatement(StandardSqmSelectTranslator.java:169)
at org.hibernate.query.sqm.sql.internal.StandardSqmSelectTranslator.translate(StandardSqmSelectTranslator.java:111)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.buildCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:224)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.resolveCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:191)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:153)
at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:413)
at org.hibernate.query.spi.AbstractQuery.list(AbstractQuery.java:1356)
at org.hibernate.query.Query.getResultList(Query.java:136)
at com.xxxx.xxxxx.mavenproject1.BaRoleManager.readWithFilter(BaRoleManager.java:153)
at com.xxxx.xxxxx.mavenproject1.BaRoleManager.main(BaRoleManager.java:201)
And this is the BaRoles class (Generate with JPA):
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.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "ba_roles")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "BaRoles.findAll", query = "SELECT b FROM BaRoles b"),
#NamedQuery(name = "BaRoles.findByRocode", query = "SELECT b FROM BaRoles b WHERE b.rocode = :rocode"),
#NamedQuery(name = "BaRoles.findByRodescri", query = "SELECT b FROM BaRoles b WHERE b.rodescri = :rodescri"),
#NamedQuery(name = "BaRoles.findByCpccchk", query = "SELECT b FROM BaRoles b WHERE b.cpccchk = :cpccchk"),
#NamedQuery(name = "BaRoles.findByRodescriEng", query = "SELECT b FROM BaRoles b WHERE b.rodescriEng = :rodescriEng")
})
public class BaRoles implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
//#TableGenerator(name = "roleGenerator", table = "cpwarn", allocationSize = 1, pkColumnName = "tablecode", valueColumnName = "autonum", pkColumnValue = "prog\\ba_roles", schema="dbo", initialValue = 0)
#TableGenerator(name = "roleGenerator", table = "cpwarn", allocationSize = 1, pkColumnName = "tablecode", valueColumnName = "autonum", pkColumnValue = "prog\\ba_roles")
#GeneratedValue(strategy = GenerationType.TABLE, generator = "roleGenerator")
#Column(name = "ROCODE", updatable = false, nullable = false)
private Integer rocode;
#Column(name = "RODESCRI")
private String rodescri;
#Column(name = "cpccchk")
private String cpccchk;
#Column(name = "RODESCRI_ENG")
private String rodescriEng;
public BaRoles() {
}
public BaRoles(Integer rocode) {
this.rocode = rocode;
}
public Integer getRocode() {
return rocode;
}
public void setRocode(Integer rocode) {
this.rocode = rocode;
}
public String getRodescri() {
return rodescri;
}
public void setRodescri(String rodescri) {
this.rodescri = rodescri;
}
public String getCpccchk() {
return cpccchk;
}
public void setCpccchk(String cpccchk) {
this.cpccchk = cpccchk;
}
public String getRodescriEng() {
return rodescriEng;
}
public void setRodescriEng(String rodescriEng) {
this.rodescriEng = rodescriEng;
}
#Override
public int hashCode() {
int hash = 0;
hash += (rocode != null ? rocode.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 BaRoles)) {
return false;
}
BaRoles other = (BaRoles) object;
if ((this.rocode == null && other.rocode != null) || (this.rocode != null && !this.rocode.equals(other.rocode))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.xxxx.xxxx.mavenproject1.BaRoles[ rocode=" + rocode + " ]";
}
}
Solved! Reverted Hibernate version from 6.0.0 alpha 4 to 5.4.12 final (Maven repository). Everything works as expected. Thank you everyone for your time and effort.
This is my first post. So, I hope the question is exciting.
I have a java program that uses Swing+JPA to work with a
PostgreSQL database. I use EclipseLink JPA 2.0 as my
Persistence Provider. My Entity Class was automatically
generated by Netbeans 7.2.1
The problem I facing is: during a updating, I change four
fields of an object retrieved using find(), then I use
merge() to update the object in the database. Three of
four changes are recognized and updated in the table,
but one of these is not updated.
I tried several things to get around this problem: I tried to change the options related to the synchronization strategy of my persistent unit, change the line position in the code (as other fields are updated), I also tried to prefix the Entity Class field with annotation #Basic(optional = false).. Any one of my attemps worked.
Here is the code of my Entity Class (Senha.java):
package model;
import java.io.Serializable;
import java.util.Date;
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.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* #author Diego Dias
*/
#Entity
#Table(name = "senha")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Senha.findAll", query = "SELECT s FROM Senha s"),
#NamedQuery(name = "Senha.findById", query = "SELECT s FROM Senha s WHERE s.id = :id"),
#NamedQuery(name = "Senha.findByGuiche", query = "SELECT s FROM Senha s WHERE s.guiche = :guiche"),
#NamedQuery(name = "Senha.findByStatus", query = "SELECT s FROM Senha s WHERE s.status = :status"),
#NamedQuery(name = "Senha.findByHchamada", query = "SELECT s FROM Senha s WHERE s.hchamada = :hchamada"),
#NamedQuery(name = "Senha.findByAtendente", query = "SELECT s FROM Senha s WHERE s.atendente = :atendente"),
#NamedQuery(name = "Senha.findByHcriacao", query = "SELECT s FROM Senha s WHERE s.hcriacao = :hcriacao"),
#NamedQuery(name = "Senha.findByDtcriacao", query = "SELECT s FROM Senha s WHERE s.dtcriacao = :dtcriacao"),
#NamedQuery(name = "Senha.findByNumeracao", query = "SELECT s FROM Senha s WHERE s.numeracao = :numeracao"),
#NamedQuery(name = "Senha.findByNchamadas", query = "SELECT s FROM Senha s WHERE s.nchamadas = :nchamadas"),
#NamedQuery(name = "Senha.findByPainel", query = "SELECT s FROM Senha s WHERE s.painel = :painel"),
#NamedQuery(name = "Senha.findMaxNumeracaoByDtcriacao", query = "SELECT MAX(s.numeracao) FROM Senha s WHERE s.dtcriacao = :dtcriacao"),
#NamedQuery(name = "Senha.findByStatusAndHchamadaAndHcriacao", query = "SELECT s FROM Senha s WHERE s.status = :status AND s.hchamada <= :hchamada AND s.hcriacao >= :hcriacao")})
public class Senha implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "guiche")
private String guiche;
#Column(name = "status")
private Character status;
#Column(name = "hchamada")
#Temporal(TemporalType.TIME)
private Date hchamada;
#Column(name = "atendente")
private Integer atendente;
#Column(name = "hcriacao")
#Temporal(TemporalType.TIME)
private Date hcriacao;
#Column(name = "dtcriacao")
#Temporal(TemporalType.DATE)
private Date dtcriacao;
#Column(name = "numeracao")
private Integer numeracao;
#Column(name = "nchamadas")
private Integer nchamadas;
#Column(name = "painel")
private Boolean painel;
public Senha() {
}
public Senha(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getGuiche() {
return guiche;
}
public void setGuiche(String guiche) {
this.guiche = guiche;
}
public Character getStatus() {
return status;
}
public void setStatus(Character status) {
this.status = status;
}
public Date getHchamada() {
return hchamada;
}
public void setHchamada(Date hchamada) {
this.hchamada = hchamada;
}
public Integer getAtendente() {
return atendente;
}
public void setAtendente(Integer atendente) {
this.atendente = atendente;
}
public Date getHcriacao() {
return hcriacao;
}
public void setHcriacao(Date hcriacao) {
this.hcriacao = hcriacao;
}
public Date getDtcriacao() {
return dtcriacao;
}
public void setDtcriacao(Date dtcriacao) {
this.dtcriacao = dtcriacao;
}
public Integer getNumeracao() {
return numeracao;
}
public void setNumeracao(Integer numeracao) {
this.numeracao = numeracao;
}
public Integer getNchamadas() {
return nchamadas;
}
public void setNchamadas(Integer nchamadas) {
this.nchamadas = nchamadas;
}
public Boolean getPainel() {
return painel;
}
public void setPainel(Boolean painel) {
this.painel = painel;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 Senha)) {
return false;
}
Senha other = (Senha) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "model.Senha[ id=" + id + " ]";
}
}
Here is the relevant code of the method that updates my object. The code inside ... does not affect the object.
EntityManagerFactory emf = ctrlCreateEntityManager();
EntityManager em = emf.createEntityManager();
...
current = em.find(Senha.class, getCurrentId());
if (current.getStatus().equals('W')) {
em.getTransaction().begin();
current.setStatus(current.getNchamadas() >= 2 ? 'L' : current.getStatus());
current.setHchamada(Calendar.getInstance().getTime());
current.setNchamadas(current.getNchamadas() + 1);
current.setPainel(true);
em.merge(current);
em.getTransaction().commit();
frame.getLbNumeroSenha().setText(formatSenha(current.getNumeracao()));
}
...
em.close();
emf.close();
When I look in the database, the fields Status Hchamada, Nchamadas are updated, but the field Painel (of type boolean), is not updated. Follow I present a excerpt of the logging from JPA/EclipseLink:
**begin transaction**
**[EL Fine]**:
Thread(Thread[AWT-EventQueue-1,4,file:...-threadGroup])--UPDATE senha SET
hchamada = ?, nchamadas = ? WHERE (id = ?)
bind => [02:15:49, 2, 4]
**[EL Finer]**:
Thread(Thread[AWT-EventQueue-1,4,file:...-threadGroup])
**commit transaction**
Looking in the code, I put a if before change the value to see if the entity managed by JPA has already the value that I want to set. Here is the code modified:
EntityManagerFactory emf = ctrlCreateEntityManager();
EntityManager em = emf.createEntityManager();
...
current = em.find(Senha.class, getCurrentId());
if (current.getStatus().equals('W')) {
em.getTransaction().begin();
current.setStatus(current.getNchamadas() >= 2 ? 'L' : current.getStatus());
current.setHchamada(Calendar.getInstance().getTime());
current.setNchamadas(current.getNchamadas() + 1);
if (current.getPainel()) {
System.out.println("Painel is already true");
}
current.setPainel(true);
em.merge(current);
em.getTransaction().commit();
frame.getLbNumeroSenha().setText(formatSenha(current.getNumeracao()));
}
...
em.close();
emf.close();
When I run the code, I got the message that indicates that my entity is already set with the value I want to write in database. So, I think the JPA/EclipseLink does not update the value if the it does not change in relation to the entity class managed by it. However, before run the code, I manually updated the database field painel to false. THen:
I did not understand why this update is not recognized when retrieve the entity.
How to force JPA to update all fields (even that do not change)?
POSSIBLE (NOT SO GOOD) SOLUTION:
Just in the moment of post this message, I realized a possible solution (not so good). Modify the code before the update to remove the entity from the database (giving a commit), and then start other transaction, updating the object. It is, removing and persisting the object again. It works.
Before I tried use remove() and merge() inside the same transaction, but it did not work.
Depending of the implementation, EclipseLink in your case, JPA will always insert all mapped columns and will only update the columns that have changed. If alternate operations are required then the queries used for these operations can be customized using API, SQL, or Stored Procedures.
You can modify this behaviour with Hibernate dynamicInsert and dynamicUpdate, but you cannot with EclipseLink. These migration guides tells you that.
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Migration/Hibernate/V3Annotations#Dynamic_Insert.2FUpdate
http://www.eclipse.org/eclipselink/documentation/2.5/solutions/migrhib002.htm
I am trying to insert a record in the database (using Java EE 6, EJB 3.1, JPA 2.0). I am getting an error that accountTypeId field is null, but i have set it up as autogenerate. Can anyone please suggest what am I doing wrong?
Following is the create table query:
create table example.account_type(
account_type_id INT NOT null PRIMARY KEY GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
account_type_desc varchar(20)
);
Following is the entity class:
EDIT: Updated the entity class as generated by NetBeans which didn't work. I also added #GeneratedValue annotation but still it didn't work.
#Entity
#Table(name = "ACCOUNT_TYPE")
#NamedQueries({
#NamedQuery(name = "AccountType.findAll", query = "SELECT a FROM AccountType a"),
#NamedQuery(name = "AccountType.findByAccountTypeId", query = "SELECT a FROM AccountType a WHERE a.accountTypeId = :accountTypeId"),
#NamedQuery(name = "AccountType.findByAccountTypeDesc", query = "SELECT a FROM AccountType a WHERE a.accountTypeDesc = :accountTypeDesc")})
public class AccountType implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY) // ADDED THIS LINE
#Basic(optional = false)
#NotNull
#Column(name = "ACCOUNT_TYPE_ID")
private Integer accountTypeId;
#Size(max = 50)
#Column(name = "ACCOUNT_TYPE_DESC")
private String accountTypeDesc;
public AccountType() {
}
public AccountType(Integer accountTypeId) {
this.accountTypeId = accountTypeId;
}
public Integer getAccountTypeId() {
return accountTypeId;
}
public void setAccountTypeId(Integer accountTypeId) {
this.accountTypeId = accountTypeId;
}
public String getAccountTypeDesc() {
return accountTypeDesc;
}
public void setAccountTypeDesc(String accountTypeDesc) {
this.accountTypeDesc = accountTypeDesc;
}
#Override
public int hashCode() {
int hash = 0;
hash += (accountTypeId != null ? accountTypeId.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 AccountType)) {
return false;
}
AccountType other = (AccountType) object;
if ((this.accountTypeId == null && other.accountTypeId != null) || (this.accountTypeId != null && !this.accountTypeId.equals(other.accountTypeId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Entities.AccountType[ accountTypeId=" + accountTypeId + " ]";
}
}
Following is the session bean interface:
#Remote
public interface AccountTypeSessionBeanRemote {
public void createAccountType();
public void createAccountType(String accDesc);
}
Following is the session bean implementation class:
#Stateless
public class AccountTypeSessionBean implements AccountTypeSessionBeanRemote {
#PersistenceContext(unitName="ExamplePU")
private EntityManager em;
#Override
public void createAccountType(String accDesc) {
AccountType emp = new AccountType(accDsc);
try {
this.em.persist(emp);
System.out.println("after persist");
} catch(Exception ex) {
System.out.println("ex: " + ex.getMessage());
}
}
}
Following is the Main class:
public class Main {
#EJB
private static AccountTypeSessionBeanRemote accountTypeSessionBean;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
accountTypeSessionBean.createAccountType("test");
}
}
Following is the error:
INFO: ex: Object: Entities.AccountType[ accountTypeId=null ] is not a known entity type.
You are not getting an error because of "accountTypeId field is null". As the error message says, the error occurs because "Entities.AccountType[ accountTypeId=null ] is not a known entity type".
The most likely reason is that AccountType is not annotated with #Entity. This problem is likely solved by adding it. Additionally it makes sense to use
#GeneratedValue(strategy = GenerationType.IDENTITY)
instead of AUTO. Auto means that the provider chooses a strategy based on the capabilities of the target database. According to the table definition it seems clear that the preferred strategy is IDENTITY.
I changed my create table query as following:
create table example.account_type(
account_type_id INT NOT null PRIMARY KEY,
account_type_desc varchar(20)
);
Then had to add the following line to the entity class (Netbeans doesn't add that):
#GeneratedValue(strategy = GenerationType.AUTO)
I can show my data in a JTable without a problem, but when I want to filter while my app is running, the JTable is not showing me data changes. I searched for it and found a class named TableModel but I can't write my AbstractTableModel. Can anyone show me how I can do this?
Personelz.Java
package deneme.persistence;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
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.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
*
* #author İbrahim AKGÜN
*/
#Entity
#Table(name = "PERSONELZ", catalog = "tksDB", schema = "dbo")
#NamedQueries({#NamedQuery(name = "Personelz.findAll", query = "SELECT p FROM Personelz p"), #NamedQuery(name = "Personelz.findByPersonelıd", query = "SELECT p FROM Personelz p WHERE p.personelıd = :personelıd"), #NamedQuery(name = "Personelz.findByAd", query = "SELECT p FROM Personelz p WHERE p.ad = :ad"), #NamedQuery(name = "Personelz.findBySoyad", query = "SELECT p FROM Personelz p WHERE p.soyad = :soyad")})
public class Personelz implements Serializable {
#Transient
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Basic(optional = false)
#Column(name = "PERSONELID", nullable = false )
private Integer personelıd;
#Column(name = "AD", length = 50)
private String ad;
#Column(name = "SOYAD", length = 50)
private String soyad;
#Column(name = "YAS")
private Integer yas;
public Personelz() {
}
public Personelz(Integer personelıd) {
this.personelıd = personelıd;
}
public Integer getPersonelıd() {
return personelıd;
}
public void setPersonelıd(Integer personelıd) {
this.personelıd = personelıd;
}
public String getAd() {
return ad;
}
public void setAd(String ad) {
String oldAd = this.ad;
this.ad = ad;
changeSupport.firePropertyChange("ad", oldAd, ad);
}
public String getSoyad() {
return soyad;
}
public void setSoyad(String soyad) {
String oldSoyad = this.soyad;
this.soyad = soyad;
changeSupport.firePropertyChange("soyad", oldSoyad, soyad);
}
public Integer getYas() {
return yas;
}
public void setYas(Integer yas){
this.yas = yas;
}
TABLEMODEL
public class TableModel extends AbstractTableModel {
String[] headers;
List<Personelz> personel;
int row;
int column;
Object[][] per;
/** Creates a new instance of TableModel */
#SuppressWarnings("empty-statement")
public TableModel(List<Personelz> p) {
this.personel = p;
column=2;
row=this.personel.size();
headers=new String[column];
headers[0]="AD";
headers[1]="SOYAD";
per={p.toArray(),p.toArray()};
}
public int getColumnCount()
{
return column;
}
public int getRowCount()
{
return row;
}
public Object getValueAt(int rowIndex, int kolonindex)
{
return per[rowIndex][kolonindex];
}
public String getColumnName(int i)
{
return headers[i];
}
I suggest reading this How to Use Tables (from the Java Tutorials Using Swing Components)
Basically the TableModel has to notify the Table of changed data by firing the appropriate Events. See here
There is a very good library called GlazedLists that makes it a lot simpler to work with lists and tables, including column sorting and row filtering.
Its definitely worth taking a look.
http://publicobject.com/glazedlists/
HTH
You should utilize the TableModelListener interface, which your JTable implements. Once you add your table to your TableModel, call the appropriate fireTableChanged()-type event that AbstractTableModel implements. This should force your JTable to update.
You will still need to implement a method to reset your data in your model when your filter operation returns. it should be in this method that you call your fireTableChanged() event. you also should ensure that you are in the AWT thread when you fire the table changed event.