With a table created using this SQL
Create Table X (
ID varchar(4) Not Null,
XDATE date
);
and an entity class defined like so
#Entity
#Table(name = "X")
public class X implements Serializable {
#Id
#Basic(optional = false)
#Column(name = "ID", nullable = false, length = 4)
private String id;
#Column(name = "XDATE")
#Temporal(TemporalType.DATE)
private Date xDate; //java.util.Date
...
}
With the above, I can use JPA to achieve object relational mapping. However, the xDate attribute can only store dates, e.g. dd/MM/yyyy.
How do I refactor the above to store a full date object using just one field, i.e. dd/MM/yyyy HH24:mm?
If you want to also store time information at the database level, use TemporalType.DATETIME:
#Column(name = "XDATE")
#Temporal(TemporalType.DATETIME)
private Date xDate; //java.util.Date
Use a TIMESTAMP column type at the database level (and xDate will be stored as 'yyyy-MM-dd HH:mm:ss.S').
Have you tried changing the #Temporal value to TemporalType.DATETIME? java.util.Date and java.sql.Date both store date and time components, the TemporalType controls which part JPA stored/pays attention to; date, time, or both.
Related
I have a parent Table, called "PN", which in it's entity contains a list of another Entity "PnDett", which is related to the first table.
I want to execute a query that will give me the list of PN with my where condition, but that will filter the list of "PnDett" also based on a where condition.
How can i achieve this?
This is the PN mapping:
#Entity
#Table(name = "PN")
public class Pn implements java.io.Serializable {
private static final long serialVersionUID = 2556879508428749494L;
#Id
#Column(name="ID_PN", unique = true, nullable = false)
private BigDecimal idPN;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="DATA_DOC")
private Date dataDoc;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="DATA_COMP_BANC")
private Date dataCompBanc;
#Column(name="STATO_PN")
private String statoPN;
#Column(name="TESTO_TESTATA")
private String testoTestata;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="DATA_INVIO_SAP")
private Date dataInvioSap;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="DATA_INS")
private Date dataIns;
#Column(name="ID_UTENTE_AGG")
private BigDecimal idUtenteAgg;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="DATA_CONTABILE")
private Date dataContabile;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="DATA_REND_INTEGR")
private Date dataRendIntegr;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="DATA_AGG")
private Date dataAgg;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pn")
private Set<PnDett> pnDetts = new HashSet<>(0);
This is the PnDett mapping:
#Entity
#Table(name = "PN_DETT")
public class PnDett implements java.io.Serializable {
private static final long serialVersionUID = 2556879508428749494L;
#Id
#Column(name="ID_PN_DETT", unique = true, nullable = false)
private BigDecimal idPNDett;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="ID_PN", nullable=false)
private Pn pn;
#OneToOne
#JoinColumn(name="ID_DOM_TIPO_SCRITTURA")
private DomTipoScrittura domTipoScrittura;
#Column(name="TIPO_DOCUMENTO")
private String tipoDocumento;
#Column(name="ID_CALCOLO")
private String idCalcolo;
#Column(name="CONTO_COGE")
private String contoCoge;
#Column(name = "IMPORTO_AVERE")
private BigDecimal importoAvere;
#Column(name = "IMPORTO_DARE")
private BigDecimal importoDare;
#OneToOne
#JoinColumn(name="ID_UTENTE")
private Utente utente;
#Column(name = "DATA_INS")
private Date dataIns;
#Column(name = "TIPO_DETTAGLIO")
private String tipoDettaglio;
#Column(name = "SE_CANC")
private Integer seCancellato;
In HQL, i wrote this query "select * from Pn firstNote where firstNote.dataContabile = (a param i put myself, in this case 20 april 2020) and firstNote.pnDetts.seCancellato = (a param i put myself, in this case 0) and firstNote.pnDetts.importoDare <> 0 or firstNote.pnDetts.importoAvere <> 0"
The results are, quite frankly, a mess. I have only two lines in my PN table that have the parameter dataContabile set at 20 april 2020, and yet i get 18 results, and the results are an Object[] which somehow containes both entities. Inside the PN object i do have the pnDetts list filtered to match the date i'm searching them for, but the other filters don't even work. How can i fix this mess? Ideally, my result should be a list of two PN objects that have the pnDetts list filtered, but i don't know how to achieve this.
Edit:
Ok, i've made an SQL query and found out that the PnDett lines related to that date that have either importoDare <> 0 or importoAvere<>0 are exactly 18, that's why i get 18 sets of objects[]. But how can i have just two PN objects, with the list inside filtered instead?
In order to make the filter work, we can make use of fetch, this will make sure that the initial query fetches all the required data.
select * from Pn firstNote join fetch firstNote.pnDetts pnd where firstNote.dataContabile = :param1 and pnd.seCancellato = :param2 and pnd.importoDare <> 0 or pnd.importoAvere <> 0
Like mentioned by Vishnu you can use join fetch, but there are many issues with such an approach. Since the result of the query are managed entities, filtering the collection is problematic. When your transaction finishes, the filtered out elements might be removed so it's important that you immediately detach all entities after such a query e.g. view entityManager.clear().
If you also want Pn objects that have empty pnDetts because nothing matches, you are out of luck with join fetch and have to use a normal join like this:
SELECT firstNote, pnd
FROM Pn firstNote
LEFT JOIN firstNote.pnDetts pnd
ON pnd.seCancellato = :param2 AND pnd.importoDare <> 0
OR pnd.importoAvere <> 0
WHERE firstNote.dataContabile = :param1
This is a scalar query which will return a Object[] so you have to collect the lists manually.
I have mapping class defined as:
#Table(name = "TEST_TABLE")
public class DBTestAccount
{
#Id
#Column(name = "UUID", nullable = false, length = 36)
private String uuid;
#Column(name = "REGION")
private String region;
#Column(name = "COUNTRY")
private String countryCode;
//getters and setters
}
Now I need to update the table. For that let's say I create following object:
DBTestAccount dbTestAccount = new DBTestAccount();
dbTestAccount.setUuid("testUUID");
dbTestAccount.setRegion("testRegion");
dbTestAccount.setCountryCode(null);
Now let's say initially in the table we have a record that has some value of COUNTRY. Inserting the above object will replace the value and make COUNTRY null. I want that it should update the data, but if the column is null, then it should ignore and do not update it. If it is non-null then it should update it. How to achieve this in hibernate? Is there an annotation to do so? If not then what is the possible solution (except using if - else). Can I create a custom annotation for this?
PS:
The underlying database is PostgreSQL.
The example you are describing can't be present in the database, because the object is not an entity yet, as it is created with new keyword and it isn't yet persisted in the database.
From your explanation, what I got, is that you want to save only changed attributes. For that purpose hibernate has the Dynamic Update annotation.
please help me.
In materialize view column type is ROWID (In the Oracle database).
Now I wont create Ejb entry class. Which type can I choose?
For example in my view
....
RECEIPT_DATE DATE NOT NULL,
...
in my entry class
#Column(name = "RECEIPT_DATETIME", nullable = true)
#Temporal(TemporalType.TIMESTAMP)
private Date receiptDateTime;
but for
D_ROWID ROWID,
I dont know :(
#Column(name = "D_ROWID", nullable = true)
private ?????? dRowId;
According to documentation the internal Datatype of Pseudocolumn rownum is NUMBER
You can use Integer type following the guide below as mappings.
http://docs.oracle.com/cd/B19306_01/java.102/b14188/datamap.htm
#Column(name = "D_ROWID", nullable = true)
private Integer dRowId;
I have my entity class like this
#Entity
public class CheckInstrument extends BaseEntity {
public CheckInstrument() {
}
#Column(nullable = false)
private Date currentCheck;
#Column(nullable = false)
private Long periodicity;
#Column
private Date nextCheck;
#Column
private boolean isExpired;`
(getters and setters)
My issues is
Сalculate nextCheck such as adding periodicity(month) to
currentCheck
Calculate isChecked property as comparing nextCheck with current
System Date.
I think your question is a pure date calculation problem, has nothing to do with Hibernate or jpa entity.
all codes are not written in IDE, not tested either:
Calculate nextCheck such as adding periodicity(month) to currentCheck
You may want to check the Calendar class
Calendar cal = Calendar.getInstance();
cal.setTime(currentCheck);
cal.add(Calendar.MONTH,1);
currentCheck = cal.getTime();
Calculate isChecked property as comparing nextCheck with current System Date.
java.util.Date implements Comparable, so you can compare two dates like:
int result = date1.compareTo(date2);
To your question: nextCheck.compareTo(new Date())
IMO, isExpired / overdued shouldn't be added as database field. because it is related current date. It would be better to get that flag by calculation, to make it real time. Well it is anyway up to your requirement.
We are generating Sales Report using Hibernate.
Scenario
When user clicks on generate report button after entering some criteria, I am fetching data from database using hibernate, then we are doing some data manipulation to generate actual report data. Report data is stored in ArrayList, which then persisted into database in CommissionSummary table, which is mapped with hibernate entity as below
CommussionSummary.java
#Column(length=100)
private String advisorName;
private String advisorCodeParent;
#Column(length=100)
private String advisorNameParent;
#Column(length=100)
private String advisorPost;
#Column
private Double percentage;
#Column
private Double diffPercentage;
#Column
private Double saleAmount;
#Column
private Long saleCount;
#Column
private Double commissionAmount;
#Column
private Integer month;
#Column
private Integer year;
Report is generated for every month.
My Question is: For 05 July 2012 user has generated data so i am storing this information in CommissionSummary table. Now user has generating the same report on 15 July 2012, then it should override earlier month data.
Override criteria should be month and year.
I believe what you need is a simple data checking.
Solution One:
1. Load data from DB and check those data for possible duplication.
2. If you find them equal, delete the older version.
Solution Two:
One other possible solution is to define your columns unique, so if a user wants to put the same data, he will be receiving some exceptions. Something like this:
#Table(name="TABLE_NAME", uniqueConstraints = {
#UniqueConstraint(columnNames={"advisorName", "advisorNameParent", "advisorPost", "percentage", "diffPercentage" , "saleAmount", "saleCount", "commissionAmount" })
#Column(name = "ADVISOR_NAME", length=100)
private String advisorName;
private String advisorCodeParent;
#Column(name = "ADVISOR_PARENT_NAME", length=100)
private String advisorNameParent;
#Column(name = "ADVISOR_POST" , length=100)
private String advisorPost;
#Column(name = "PERCENTAGE")
private Double percentage;
#Column (name = "DIFF_PERCENTAGE")
private Double diffPercentage;
#Column (name = "SALE_AMOUNT")
private Double saleAmount;
#Column (name = "SALE_COUNT")
private Long saleCount;
#Column (name = "COMMISSION_AMOUNT")
private Double commissionAmount;
Using this, you can check if there were some errors you can do your desired action.
Get the CommissionSummary for the given month an year using a HQL query:
select c from CommissionSummary where c.year = :year and c.month = :month
If not null, delete it:
session.delete(existingCommissionSummary);
Then save the new one.