How to save a jpa object within a for loop - java

I have a list of users which I would like to send invite emails to, after I send the email, i would like to save that person in a separate table so incase server goes down we won't be sending double emails since we know who was the last person we sent email to. this is the code:
#play.db.jpa.NoTransaction
public void sendInvite() {
Long lastUser = (Long) User.find("select MAX(id) from User").fetch().get(0);
Long lastId = (Long) Contact.find("select MAX(id) from Contact").fetch().get(0);
for (i=lastContacted; i < totalNumUsers; i++) {
UserContact contact = new UserContact();
contact.firstName = user.firstName;
contact.lastName = user.lastName;
contact.email = user.email;
if (validateEmail(user) == false) {
continue;
}
sendInviteEmail(user);
saveContact(contact); //THIS DOESN'T TAKE PLACE UNTIL END OF THE LOOP
Thread.sleep(2000);
}
}
The Problem is that the saved contact, is not getting saved in the database until the end of the for loop. i have tried:
contact.em().persist(contact);
contact.em().flush();
but that is not working either
* i would also want to add that the method is being run from a Job and not from a Controller.

If you do all this in a transaction, and the server goes down, the transaction won't be committed, and even if you flush during the transaction, nothing will be written to the database. Foe each and every contact, you need to open a new transaction, save the contact in this new transaction, then commit the transaction.

Related

How to decide when to update, delete and insert

I am using spring data jpa for creating services. I have to do insert, update and delete operation on one save button. for save and update I am using repository save method in my code. For deciding need to do update or insert I am checking count of records.
If I am sending one record then I am successfully able to do save and update operations.
But my problem is that when I am sending two record which already present is db
that need to go for update. but In my situation I am checking count of record so its going for save instead of update.
Can any one tell me what condition need to check more then it will go for update ? Or
Tell me any another way for to decide when to go for update,when to go for insert and when to go for delete?
RoomInvestigatorMappingService class
public String updatePiDetails(List<PiDetails> roomInvestMapping) {
List<RoomInvestigatorMapping> currentRecord = new ArrayList<RoomInvestigatorMapping>();
for (PiDetails inputRecorObj : roomInvestMapping) {
currentRecord = roomInvestigatorMappingRepo.findByNRoomAllocationId(inputRecorObj.getnRoomAllocationId());
}
int currentRecordCount = currentRecord.size();
int inputRecordCount = roomInvestMapping.size();
// update existing record
if (inputRecordCount == currentRecordCount) {
for (PiDetails inputObject : roomInvestMapping) {
for (RoomInvestigatorMapping currentRecordObj : currentRecord) {
currentRecordObj.nInvestigatorId = inputObject.getnInvestigatorId();
currentRecordObj.nPercentageAssigned = inputObject.getnPercentageAssigned();
currentRecordObj.nRoomAllocationId = inputObject.getnRoomAllocationId();
roomInvestigatorMappingRepo.saveAll(currentRecord);
}
}
}
//insert new record
if (inputRecordCount > currentRecordCount) {
for (PiDetails inputObject : roomInvestMapping) {
RoomInvestigatorMapping investObj = new RoomInvestigatorMapping();
investObj.nInvestigatorId = inputObject.getnInvestigatorId();
investObj.nRoomAllocationId = inputObject.getnRoomAllocationId();
investObj.nPercentageAssigned = inputObject.getnPercentageAssigned();
roomInvestigatorMappingRepo.save(investObj);
}
}
return "sucessfully";
}
RoomInvestigatorMappingRepository interface
#Query("select roomInvestMapping from RoomInvestigatorMapping as roomInvestMapping where nRoomAllocationId=?1")
List<RoomInvestigatorMapping> findByNRoomAllocationId(Integer nRoomAllocationId);
Json Input
[
{
"nInvestigatorId": 911294,
"nPercentageAssigned": 50,
"nRoomAllocationId": 1
},
{
"nInvestigatorId": 911294,
"nPercentageAssigned": 50,
"nRoomAllocationId": 2
}
]
Just use CrudRepository.existsById(ID id)
The documentation says:
Returns whether an entity with the given id exists.

Java Scheduling task

I am developing a spring mvc project where a notification will send to user mobile.User will select a datetime at format 'yyyy-MM-dd HH:mm' from frontend and save it to the database.when system time reach that time a notification will be send to the user mobile .
I created scheduler like this
#Component
public class NotificationScheduler extends BaseService {
#Scheduled(fixedRate = 300000)
public void sendNotification() {
Date currentDate = new Date();
System.err.println("HHHHHHHHHKKKKKK");
List<ImageInfo> listImageInfo = imageInfoDao.getImageOfParticularDate(currentDate);
}
}
this is my dao function which run a wuery to database
public List getImageOfParticularDate(Date date) {
session = getSession();
session.beginTransaction();
List<ImageInfo> imageInfoList = session.createQuery("select img from ImageInfo img where img.publishedTime =:publishedTime ").setParameter("publishedTime", date).list();
session.getTransaction().commit();
return imageInfoList;
}
this code is checking repeatedly at 5 min interval whether system time equal to publish time.if it is equal then a notification will be sent.I used Date type in model and Date type column in database. I want to know my approach is right or wrong because i can not get desire output.
Why don't you use a debug mode? Change, your the time rate you use in order to not wait too much, but I think you could determine that yourself, could you?

use of multithreading for downloading in java

I'm trying to concurrently download HTML-code of websites whose urls are stored in the database (about 3 millions of entries).
It's obvious that I should use multithreading technology but I get into trouble how to do it in java.
Here's how I used to do it without multithreading:
final Connection c = dbConnect(); // register jdbc-driver and establish connection
checkRequiredDbAndTables(); // here we check the existence of the Db and necessary tables
try {
// now get list of urls from the db
String sql = "select id, website_url, category_id from list_of_websites";
PreparedStatement ps = c.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
// column numeration in ResultSet is from 1 !
final long id = rs.getInt(1); // get website id
final String url = rs.getString(2); // get website url
System.out.println("Category: " + rs.getString(3) + " " + id + " " + url);
if ( isValidURL(url) && connectionOK(url) ) {
// checked url syntax and connection
String htmlInPage = downloadHTML(url);
if (!htmlInPage.equals("")) {
// add result to db
insertDataToDb( c, id, htmlInPage);
}
}
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
closeConnection(c); // database connection closed
The function donloadHTML uses JSoup library to do the main work.
Feels like my task is a kind of "producer consumer problem". I suppose that it can be represented in a such way: there's a buffer, containing N links; some processes getting the links from it and downloading HTML; and a process, which aim is to load new urls from the db into the buffer as it gets empty.
But I completely don't know how to do it. I've heard of Threads and ExecutorService providing ThreadPools but its really confusing for me.
You may want to use a Thread pool that has fixed amount of thread. Your program will first create a thread pool. Then it will read URLs from database. When a URL is read, the program will start a new task to download its content.
You program may maintain a queue. When a task finish downloading HTMLs, it can push the URL and the result together into a queue. When the main thread finish reading URLs and starting tasks, it can wait for the queue. Once the queue have any responses, take the response out and write it to database. The main thread can count how many responses are received, when it counts to the number of URLs, then all task was finish.
Your program can write a class for storing the response with the URL, for example:
class response {
public String URL;
public String result;
public response(String u, String r) { this.URL = u; this.result = r; }
}
If you still have any problem implementing or understanding ( I may not explain this clear enough, it is 00:40 now and I will probably go to sleep soon. ), please leave comments. If you want code, please also leave comments.
Main thread:
Start X "downloading" threads
Run query shown in question. for each record:
Add data from query to an ArrayBlockingQueue
Add end-of-data marker to queue
Wait for threads to stop (optional)
Return from main
Download thread:
Get data from queue. while not end-of-data marker:
Download HTML
Insert HTML to database
Put end-of-data marker back into queue for other threads to find
Exit thread

How to count number of clicks on button and save in MySql database? The clicks in a new session should be added to the existing value

This is the DAO I have created:
public Poll updatePoll(int id){
Session s = factory.getCurrentSession();
Transaction t = s.beginTransaction();
Poll poll = (Poll) s.get(Poll.class, id);
Citizen citizen = (Citizen) s.get(Citizen.class, 1);
List<Poll> list = citizen.getPolledList();
boolean check = list.contains(poll);
if(!check){
Query q = s.createSQLQuery("update Poll set poll_count = poll_count + 1 where poll_id = id");
q.executeUpdate();
s.update(poll);
}else{
return poll;
}
s.close();
return poll;
}
This is the Action created:
public String submitVote(){
ServletContext ctx = ServletActionContext.getServletContext();
ProjectDAO dao = (ProjectDAO)ctx.getAttribute("DAO");
Poll poll = dao.updatePoll(poll_id);
String flag = "error";
if (poll != null){
ServletActionContext.getRequest().getSession(true).setAttribute("POLL", poll);
flag = "voted";
}
return flag;
}
I know I have been going horribly wrong and the code I'm posting might be utter rubbish. But I hope the intent is clear, thus if possible please lent me a helping hand. My project is mainly in JSP (Struts 2), jQuery and MySQL 5.1, so please do not suggest PHP codes as I've found earlier.
The framework is used to wrap the servlet stuff from user, you should use its features if you want doing something like
ServletActionContext.getRequest().getSession(true)
But
Map m = ActionContext.getContext().getSession();

Why does app engine bill me less when the below code is wrapped in a transaction?

I have verified this multiple times using appstats. When the below code is NOT wrapped in a transaction, JDO performs two datastore reads and one write, 3 RPC's, at a cost of 240. Not just the first time, every time, even though it is accessing the same record every time hence should be pulling it from cache. However, when I wrap the code in a transaction as above, the code makes 4 RPC's: begin transaction, get, put, and commit -- of these, only the Get is billed as a datastore read, so the overall cost is 70.
If it's pulling it from cache, why would it only bill for a read? It would seem that it would bill for a write, not a read. Could app engine be billing me the same amount for non-transactional cache reads as it does for datastore reads? why?
This is the code WITH transaction:
PersistenceManager pm = PMF.getManager();
Transaction tx = pm.currentTransaction();
String responsetext = "";
try {
tx.begin();
Key userkey = obtainUserKeyFromCookie();
User u = pm.getObjectById(User.class, userkey);
Key mapkey = obtainMapKeyFromQueryString();
// this is NOT a java.util.Map, just FYI
Map currentmap = pm.getObjectById(Map.class, mapkey);
Text mapData = currentmap.getMapData(); // mapData is JSON stored in the entity
Text newMapData = parseModifyAndReturn(mapData); // transform the map
currentmap.setMapData(newMapData); // mutate the Map object
tx.commit();
responsetext = "OK";
} catch (JDOCanRetryException jdoe) {
// log jdoe
responsetext = "RETRY";
} catch (Exception e) {
// log e
responsetext = "ERROR";
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
resp.getWriter().println(responsetext);
This is the code WITHOUT the transaction:
PersistenceManager pm = PMF.getManager();
String responsetext = "";
try {
Key userkey = obtainUserKeyFromCookie();
User u = pm.getObjectById(User.class, userkey);
Key mapkey = obtainMapKeyFromQueryString();
// this is NOT a java.util.Map, just FYI
Map currentmap = pm.getObjectById(Map.class, mapkey);
Text mapData = currentmap.getMapData(); // mapData is JSON stored in the entity
Text newMapData = parseModifyAndReturn(mapData); // transform the map
currentmap.setMapData(newMapData); // mutate the Map object
responsetext = "OK";
} catch (Exception e) {
// log e
responsetext = "ERROR";
} finally {
pm.close();
}
resp.getWriter().println(responsetext);
With the transaction, the PersistenceManager can know that the caches are valid throughout the processing of that code. Without the transaction, it cannot (it doesn't know whether some other action has come in behind its back and changed things) and so must validate the cache's contents against the DB tables. Each time it checks, it needs to create a transaction to do so; that's a feature of the DB interface itself, where any action that's not in a transaction (with a few DB-specific exceptions) will have a transaction automatically added.
In your case, you should have a transaction anyway, because you want to have a consistent view of the database while you do your processing. Without that, the mapData could be modified by another operation while you're in the middle of working on it and those modifications would be silently lost. That Would Be Bad. (Well, probably.) Transactions are the cure.
(You should also look into using AOP for managing the transaction wrapping; that's enormously easier than writing all that transaction management code yourself each time. OTOH, it can add a lot of complexity to deployment until you get things right, so I could understand not following this piece of adviceā€¦)

Categories