Persist entity using Java Hibernate API and update if already exists - java

Have the following table and Java Entity:
CREATE TABLE search_terms (
id int(100) NOT NULL AUTO_INCREMENT,
term varchar(255) NOT NULL DEFAULT '',
last_search_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
search_count int(100) NOT NULL DEFAULT '0',
user_email varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
public class SearchTerms implements Serializable {
private Long id;
private String term;
private Timestamp lastSearchDate;
private int searchCount;
private String userEmail;
Want to persist java objects of the given type into the table above.
Example:
List<String> searchTerms = Arrays.asList("test1", "test2", "test3");
saveSearchParams(searchTerms);
If any of those terms exist in the table, I want to increment searchCount else save as a new row.
Need to use JPA.em().merge(o) etc and not have sql insert/update queries
Added the following constant on the two columns but JPA.em().merge(o) keeps inserting new rows.
#Table(name="search_terms", uniqueConstraints= { #UniqueConstraint(columnNames = {"term", "user_email"})})
saveSearchParams() {
searchTerms.forEach(o -> {
SearchTerms term = new SearchTerms();
term.setSearchCount(1);
term.setTerm((String) o);
term.setUserEmail(email);
jpaApi.em().merge(term);
});
}
Any help on or documentation is appreciated.

Merge can both update and insert, but you should check if the object exists in DB to see if you have to set the counter to one or add one to it, for this you will have to throw a query for each element.
try this:
saveSearchParams() {
searchTerms.forEach(o -> {
//search for example by id or in any other way
SearchTerms term = jpaApi.em().find(SearchTerms.class, o.getId());
if (term == null){
term = new SearchTerms();
term.setSearchCount(1);
}else{
term.setSearchCount(term.getSearchCount()+1);
}
term.setTerm((String) o);
term.setUserEmail(email);
jpaApi.em().merge(term);
});
}

Related

Java display records from a table based on records in other tables

I'm very new to using databases and SQL in general and I'm having some trouble figuring out a function that will allow me to display records from a table in my jdbc database based on data from other tables in the database. I will illustrate below:
Example of "DEMANDS" table (column headers, "ID" is the primary key):
NAME|ADDRESS|DESTINATION|DATE|TIME|ID
Example of "DRIVERS" table ("REGISTRATION" is the primary key):
USERNAME|PASSWORD|REGISTRATION|NAME
Example of "JOURNEY" table ("JID" is the primary key,"REGISTRATION" is a foreign key)
JID|NAME|ADDRESS|DESTINATION|DISTANCE|REGISTRATION|DATE|TIME|STATUS
Below is the code that I have that is used to display tables on a jsp file:
public String retrieve(String query) throws SQLException {
select(query);
return makeTable(rsToList());//results;
}
private void select(String query){
try {
statement = connection.createStatement();
rs = statement.executeQuery(query);
//statement.close();
}
catch(SQLException e) {
System.out.println("way way"+e);
//results = e.toString();
}
}
private String makeTable(ArrayList list) {
StringBuilder b = new StringBuilder();
String[] row;
b.append("<table border=\"3\">");
for (Object s : list) {
b.append("<tr>");
row = (String[]) s;
for (String row1 : row) {
b.append("<td>");
b.append(row1);
b.append("</td>");
}
b.append("</tr>\n");
} // for
b.append("</table>");
return b.toString();
}//makeHtmlTable
private ArrayList rsToList() throws SQLException {
ArrayList aList = new ArrayList();
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount(); //number of column
String columnName[] = new String[count];
for (int i = 1; i <= count; i++)
{
columnName[i-1] = metaData.getColumnLabel(i);
}
aList.add(columnName);
int cols = rs.getMetaData().getColumnCount();
while (rs.next()) {
String[] s = new String[cols];
for (int i = 1; i <= cols; i++) {
s[i-1] = rs.getString(i);
}
aList.add(s);
} // while
return aList;
} //rsToList
All of this code works fine and if I pass in a query into the "Retrieve" function such as:
String query = "select * from DRIVERS";
It will display all of the records of the "DRIVERS" table.
What I am wanting to do though, is only list drivers from the driver table that are available at the time specified in the demand (meaning their registration is not currently in a record in the journey table at the same time as the demand) If possible, I would also only like to display the "NAME" and "REGISTRATION" columns as oppose to the whole record.
I would really appreciate some help with this as I've searched around for solutions for quite some time and have not been able to work out a function that will achieve the desired outcome.
Cheers,
Creation of tables script:
-- --------------------------------------------------------
--DROP Table Demands;
CREATE TABLE Demands (
Name varchar(20),
Address varchar(60),
Destination varchar(60),
Date date DEFAULT NULL,
Time time DEFAULT NULL,
Status varchar(15) NOT NULL,
id INT primary key
);
-- --------------------------------------------------------
--DROP Table Drivers;
CREATE TABLE Drivers (
username varchar(20),
password varchar(20),
Registration varchar(10),
Name varchar(20),
PRIMARY KEY (Registration)
);
-- --------------------------------------------------------
--DROP Table Journey;
CREATE TABLE Journey (
jid INT primary key
Destination varchar(60),
Distance integer NOT NULL DEFAULT 1,
Registration varchar(10) NOT NULL,
Date date NOT NULL,
Time time DEFAULT NULL
);
The following query may answer your question.
SELECT Drivers.Name, Drivers.Registration
FROM Drivers
LEFT JOIN Journey ON Journey.Registration = Drivers.Registration
LEFT JOIN Demands ON Demands.Date = Journey.Date
WHERE Demands.id IS NULL;
This joins JOURNEY and DRIVER based on the foreign key relation. It then outer-joins DEMANDS and JOURNEY based on an implicit relation that is DATE. Finally we only keep records that fail the outer join condition.
The model has a major flaw though as the relation between DEMANDS and JOURNEY is based on a field of type Date, as far as one can tell by what your provided.

how to use like clause in mysql for variable of double type using hibernate

I have table shown below. The clause of like is not working for variable of double type in hibernate and mysql. how like clause will work double or what could be the work around to achieve this. I'm getting no exception just the obj the returned is null.
Table:-
CREATE TABLE `loc_location` (
`location_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`latitude` double NOT NULL,
`longitude` double NOT NULL,
`creation_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`status` char(1) NOT NULL DEFAULT 'A' COMMENT 'A-Approved\nD-Drafted\nP-Pending\nR-Reject\nS-Scheduled',
PRIMARY KEY (`location_id`),
UNIQUE KEY `location_id_UNIQUE` (`location_id`),
UNIQUE KEY `latitude_UNIQUE` (`latitude`),
UNIQUE KEY `longitude_UNIQUE` (`longitude`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
Table Values:-
location_id latitude longitude creation_date status
1 19.175934 72.8622649 2015-08-22 14:09:31 A
2 19.177283 72.8636139 2015-08-22 14:09:31 A
3 19.174585 72.8609159 2015-08-22 14:09:31 A
Query:- longitude = 72.862 and latitude = 19.175
select this_.location_id as location1_16_0_, this_.creation_date as creation2_16_0_, this_.latitude as latitude3_16_0_, this_.longitude as longitud4_16_0_, this_.status as status5_16_0_ from loc_location this_ where this_.longitude like ? and this_.latitude like ?
Hibernate method:-
public <T extends Serializable> T getEntityWithLikeClause(T x, Map<String, Object> ceriteriaMap, Session session) throws PersistenceException{
T obj=null;
Criteria criteria = null;
try {
criteria= session.createCriteria(x.getClass());
if(ceriteriaMap!=null && criteria !=null){
Set<String> set=ceriteriaMap.keySet();
for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
String ceriteria = iterator.next();
Object value = ceriteriaMap.get(ceriteria);
criteria.add(Restrictions.like(ceriteria, value));
}
}
obj = (T) criteria.uniqueResult();
}catch (Exception e) {
throw new PersistenceException(e);
}
return obj;
}
Where ceriteriaMap as following and longitude1 = 72.862 and latitude1 = 19.175:-
Map<String, Object> ceriteriaMap = new HashMap<String, Object>();
ceriteriaMap.put("lat", latitude1);
ceriteriaMap.put("lng", longitude1);
Restrictions.ilike cannot be used for numeric fields.
Default Syntax:
Restrictions.ilike(fieldName, SearchTerm, MatchMode.ANYWHERE (Optional) )
| | |
String String MatchMode (optional argument)
So you can't be able to pass a numeric value to a String argument. Even if you pass it as String.valueOf(numbercValue), you'll get exception because hibernate will try to convert it to numeric datatype as per your hbm or annotation configuration
I've used the following code to mix like with criteria.
critria.add(
Restrictions.sqlRestriction(" column_name LIKE '%"+SearchTerm+"%' "))
| |
Column Name (Not fieldName) Search Term prefixed and Suffixed with % as per needs
You can't use LIKE for non varchar(string) types. It works only for String patterns.
In any numeric cases, you have to use gt/lt logic or change field to varchar and parse this fiels to double via row mapper.

Fetch the data between Two date in Hibernate Jave with MySQL?

Am new to Java server side and i creating JSON Links using Jersey library. In my project am Using Hibernate to Get the data from MySQL database. I want to fetch the data between two dates in MySQL.But Query is Not Working properly.
MySQL Table
CREATE TABLE `order_headers` (
`bill_number` int(10) NOT NULL AUTO_INCREMENT,
`order_number` varchar(100) DEFAULT NULL,
`table_number` varchar(20) NOT NULL,
`payment_type` varchar(20) DEFAULT NULL,
`discount` double NOT NULL,
`payment_status` varchar(30) DEFAULT NULL,
`order_status` varchar(20) DEFAULT NULL,
`order_date` date NOT NULL,
`grand_total` decimal(7,2) NOT NULL,
`upt_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`bill_number`)
)
Depends upon the order_date column in the table to fetch data.
Hibernate Annotation Class
#Entity
#Table(name = "order_headers")
public class Order_headers {
#Id #GeneratedValue
#Column(name = "bill_number")
private String bill_number;
#Column(name = "order_number")
private String order_number;
#Column(name = "order_value")
private double order_value;
//format YYYY-mm-dd
#Column(name = "order_date")
private String order_date;
//All other Variables and Getter Setters
}
Query Used to fetch data in JAVA
//Query i used
/*FROM Order_headers oh WHERE oh.merchant_code = :merchant_code AND oh.branch_code = :branch_code AND DATE_FORMAT(oh.order_date,'%d-%m-%Y') >= :from_date AND DATE_FORMAT(oh.order_date,'%d-%m-%Y') <= :to_date ORDER BY DATE_FORMAT(oh.order_date,'%d-%m-%Y') ASC*/
Query query = session.createQuery("FROM Order_headers oh WHERE oh.merchant_code = :merchant_code AND oh.branch_code = :branch_code AND DATE_FORMAT(oh.order_date,'%d-%m-%Y') >= :from_date AND DATE_FORMAT(oh.order_date,'%d-%m-%Y') <= :to_date ORDER BY DATE_FORMAT(oh.order_date,'%d-%m-%Y') ASC");
query.setParameter( "merchant_code", merchant_code );
query.setParameter( "branch_code", branch_code );
query.setParameter( "from_date", from_date );
query.setParameter( "to_date", to_date );
In table have data till 22-06-2015
I check with two condition:
When i pass these parameters merchant_code=1&branch_code=1&from_date=10-02-2015&to_date=16-07-2015 it fetch all the data between two dates.
When i pass these parameters merchant_code=1&branch_code=1&from_date=10-02-2015&to_date=15-07-2015 this not even a single data.When i give date from 01-07-2015 to 15-07-2015 in to_date parameter same problem continues.
Am search it in Google all of them give same query what i used,but i am not able find out the issue.Can any one know help me to solve this issue.
Try to use Between
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String fromDate= format.parse(from_date);
String toDate= format.parse(to_date);
Query query = session.createQuery("FROM Order_headers oh WHERE oh.merchant_code = :merchant_code AND oh.branch_code = :branch_code AND oh.order_date BETWEEN fromDate AND toDate");
query.setParameter( "fromDate", fromDate);
query.setParameter( "toDate", toDate );

save XML to mysql using hibernate

I want to save an XML file into LONGTEXT field mysql through hibernate. I'm a bit new to hibernate and really appropriate your advice.
mysql table was created.
CREATE TABLE testdata (
TD_ID INT(11) NOT NULL AUTO_INCREMENT,
XML_VAL LONGTEXT NULL,
PRIMARY KEY (TD_ID)
Hibernate entity is also created.
#Lob
#Column(name="XML_VAL")
public String getXmlVal() {
return xmlVal;
}
public void setXmlVal(String xmlVal) {
this.xmlVal = xmlVal;
}
No need to use #Lob.
#Column(name = "XML_VAL", length = 65535)
You define the length of your text which needs to be inserted.

How to choose DDL Primary Key constraint names with JPA/Hibernate

There exists a proprietary hibernate annotation to specify the Foreign Key constraint names that are used at DDL generation time: org.hibernate.annotations.ForeignKey.
Is there also a way to specify the Primary Key constraint names?
Not possible with standard JPA and not supported by Hibernate for Primary Key constraints neither.
There is actually a very old issue about this feature request (HB-1245) but it looks like it doesn't get much attention.
You can control the generated PK constraint names with a few small mods in a custom dialect. For example, here's how to do it in Oracle (the same approach works for SQLServer & DB2):
public class CustomOracleDialect extends org.hibernate.dialect.Oracle10gDialect {
private CustomTableExporter customTableExporter;
public CustomOracleDialect () {
super();
customTableExporter = new CustomTableExporter(this);
}
#Override
public Exporter<Table> getTableExporter () {
return customTableExporter;
}
static class CustomTableExporter extends StandardTableExporter {
private final static int MAX_TABLE_NAME_LENGTH = 30;
public CustomTableExporter (Dialect dialect) {
super(dialect);
}
#Override
public String[] getSqlCreateStrings (Table table, Metadata metadata) {
final String[] sqlCreateStrings = super.getSqlCreateStrings(table, metadata);
//-- replace " primary key" with " constraint TABLE_NAME_PK primary key "
final String namedPkConstraint = " constraint " + StringUtils.truncate(table.getName(), MAX_TABLE_NAME_LENGTH - 3) + "_PK primary key ";
for (int i = 0; i < sqlCreateStrings.length; ++i) {
sqlCreateStrings[i] = StringUtils.replace(sqlCreateStrings[i], " primary key ", namedPkConstraint);
}
return sqlCreateStrings;
}
}
}
This will change the generated DDL from this:
-- BEFORE:
create table FOO_ENTITY (
FOO_ENTITY_ID number(19, 0) not null,
JOB_NAME varchar2(128 char) not null,
primary key (FOO_ENTITY_ID)
);
To this :
-- AFTER:
create table FOO_ENTITY (
FOO_ENTITY_ID number(19, 0) not null,
JOB_NAME varchar2(128 char) not null,
constraint FOO_ENTITY_PK primary key (FOO_ENTITY_ID)
);
The class org.hibernate.mapping.PrimaryKey does the following:
public String sqlConstraintString(Dialect dialect) {
StringBuilder buf = new StringBuilder("primary key (");
Iterator iter = getColumnIterator();
while ( iter.hasNext() ) {
buf.append( ( (Column) iter.next() ).getQuotedName(dialect) );
if ( iter.hasNext() ) {
buf.append(", ");
}
}
return buf.append(')').toString();
}
The solution would be to override this method and return a string starting with "constraint YOUR_CONSTRAINT_NAME primary key" to make it possible. Unfortunately there's no way of overriding this.
If you're talking about choosing the name of your primary key (in the database), Hibernate can not do that.
Remember, Hibernate is a framework that is primarly focused on mapping objects, not on the creation/maintenance of database entities.
With regards to defining the primary key, the following link (particularly 2.2.3.2) might be helpful: Mapping identifier properties in the JBoss Hibernate guide

Categories