Error: Hibernate could not initialize proxy - no Session - java

ReportService Code
private void generatePaySummary() {
try {
Map params = new HashMap();
params = getOrganizationInfo(params);
params.put("rptsubtitle", "Payroll Date: "+date_formatter.format(tbpaydate.getDate()));
int i = cboDept.getSelectedIndex();
int deptno = 0;
if (i != -1) deptno = (Integer)deptnos.get(i);
ReportService srv = new ReportService();
List empids = srv.getEmployeesInPayroll(deptno, tbpaydate.getDate());
if (!empids.isEmpty()) {
PayslipService.setEmployees(empids);
PayslipService.setPayDate(tbpaydate.getDate());
RepGenService repsrv = new RepGenService();
JRBeanCollectionDataSource jbsrc = new JRBeanCollectionDataSource(PaySummaryFactory.getPaySummary());
repsrv.generateReport(false, "/orgpayroll/reports/jasper/payrollsummary.jasper", true, params, jbsrc);
}
else
SysUtils.messageBox("No employees in payroll on "+date_formatter.format(tbpaydate.getDate())+"!");
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Error" + e.getMessage());
}
}
I am trying to execute a function which will open a jasper report template.
The function works if it will only process 1 employee from the database, but if I process more with the same date, it says Hibernate could not initialize proxy - no Session.

This means that you have one collection with lazy fetchType.
you can solve it by changing it to EAGER mode
So go to ReportService class and turn your employee collection's fetchType to EAGER. Or add (fetch=fetch = FetchType.EAGER)

Related

Getting details from database Spring Boot , Exception error

I am trying to get data by multiple data from database on the basis of multiple Ids using Spring boot.
Basically it is a GET call which takes request parameters as a list of IDs and return response accordingly. IDs are unique in database
Url : api/details/1a,2a,3b
I am getting response as:
Get(value = "api/details/{Ids})
{
[id="1a",name="Raj", interest="Football"],
[id="2a",name="Tom", interest="Cricket"]
[id="3b",name="Kane", interest="Baseball"]
}
It is fine. But when i am giving a wrong Id, I am getting response as:
Url : api/details/xyz,abc,3b
{
null,
null,
[id="3b",name="Kane", interest="Baseball"]
}
I am expecting that instead of null it show say that the ID is not present along with Status code. Something like
{
2-Not found,3-Not Found,
id="3b",name="Kane", hobby="Baseball,
}
My controller class is like:
#RequestMapping(value = "api/details{Ids}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<Game>>
getMultipleDetails(#PathVariable("Idss") String Idss) {
HttpHeaders headers = new HttpHeaders();
List<String> ids = Arrays.asList(Idss.split(","));
List<Game> list = new ArrayList<>();
Game details= null;
for (String id : ids) {
details= da.getMultipleDetails(id);
list.add(devices);
}
if (details== null) {
throw new RuntimeException(HttpStatus.NOT_FOUND.toString());
}
return new ResponseEntity<List<Game>>(list, headers, HttpStatus.OK);
}
}
My repository class is like:
public Device getMultipleDetails(String id) {
Game details= null;
try {
details= jdbcTemplate.queryForObject("SELECT * FROM table_name WHERE Id = ?",new DeviceRowMapper(), id);
} catch (Exception e) {
// Log the system generated Id
String systemRefId = String.valueOf(System.currentTimeMillis());
LOGGER.error(systemRefId, e);
//throw new DatabaseException(systemRefId, e);
}
return details;
}
Game is my model class that conatins id, name, hobby
As you're setting the ResponseEntity<List<Game>> you should only return a List with Game objects inside.
Not sure why you want to return the failed ones in the same List but as a workaround I will set id of the not found and, in the fields name and Game I will set 'Not found' instead of returning null objects. For example:
public Device getMultipleDetails(String id) {
Game details = new Game();
try {
details= jdbcTemplate.queryForObject("SELECT * FROM table_name WHERE Id = ?",new DeviceRowMapper(), id);
//If details is not null but it's empty
if (StringUtils.IsEmpty(details.getId())) {
details.setId(id);
details.setName("Not Found");
details.setGame("Not Found");
}
} catch (Exception e) {
// Log the system generated Id
String systemRefId = String.valueOf(System.currentTimeMillis());
LOGGER.error(systemRefId, e);
//If details is null it will trow null pointer exception
details = new Game();
details.setId(id);
details.setName("Not Found");
details.setGame("Not Found");
}
return details;
}
I strongly recommend you to rename the field Game in you Game class. A field should not duplicate the name of its containing class.
It's confusing to have a class member with the same name (case differences aside) as its enclosing class. This is particularly so when you consider the common practice of naming a class instance for the class itself.
Best practice dictates that any field or member with the same name as the enclosing class be renamed to be more descriptive of the particular aspect of the class it represents or holds.
I would recommend to rename it to something like typeOfGame for example.
You should manage the empty objects, and manage the message also, the code should be like this, because if not, only the last detail is the one evaluated, thats why the exception is not raised.
for (String id : ids) {
details= da.getMultipleDetails(id);
list.add(devices);
if (details== null) {
throw new RuntimeException(HttpStatus.NOT_FOUND.toString());
}
}

Spring - Two hibernate update queries are executed instead of one

I am working Spring and Hibernate. I have a requirement where I need to update a particular field by adding a number to it. Since multiple threads could execute it at the same time, while updating I check the field value with the old value. So if nothing was updated that means it was incremented by some other thread and we trigger a retry.
CompanyService
public Company getAndIncrementRequestId(final int companyId, int retry) throws Exception {
Optional<Company> companyOptional = companyRepository.findById(companyId);
if (!companyOptional.isPresent()) {
throw new EntityNotFoundException("Company not found for given id" + companyId);
}
Company company = companyOptional.get();
int oldRequestId = company.getRequestId();
int requestId;
if (oldRequestId == Integer.MAX_VALUE) {
requestId = 1;
} else {
requestId = oldRequestId + 1;
}
company.setRequestId(requestId); //--------------------------> PROBLEM
int result = companyRepository.updateRequestId(companyId, requestId, oldRequestId);
if (result == 0) {
if (retry < 0) {
throw new Exception("Unable to get requestId");
}
LOG.warn("Retrying since there was some update on requestId by some other thread");
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
LOG.warn("Unexpected InterruptException occurred while trying to get requestId");
}
return getAndIncrementRequestId(companyId, retry - 1);
}
return company;
}
CompanyRepository
#Transactional
public interface CompanyRepository extends CrudRepository<Company, Integer> {
Optional<Company> findById(String id);
#Modifying(clearAutomatically = true)
#Query("update Company c set c.requestId = :requestId WHERE c.id = :companyId AND c.requestId = :oldRequestId")
int updateRequestId(#Param("companyId") Integer companyId, #Param("requestId") Integer requestId,#Param("oldRequestId") Integer oldRequestId);
}
But this above code in Service will trigger two hibernate updates one which set the requestId with lastest requestId and the other the actual update. Could observe two queries in the log after setting show-sql as true.
But if the line ,
company.setRequestId(requestId);
Is moved down after the companyRepository.updateRequestId() it works fine.
Working CompanyService
public Company getAndIncrementRequestId(final int companyId, int retry) throws Exception {
Optional<Company> companyOptional = companyRepository.findById(companyId);
if (!companyOptional.isPresent()) {
throw new EntityNotFoundException("Company not found for given id" + companyId);
}
Company company = companyOptional.get();
int oldRequestId = company.getRequestId();
int requestId;
if (oldRequestId == Integer.MAX_VALUE) {
requestId = 1;
} else {
requestId = oldRequestId + 1;
}
int result = companyRepository.updateRequestId(companyId, requestId, oldRequestId);
if (result == 0) {
if (retry < 0) {
throw new Exception("Unable to get requestId");
}
LOG.warn("Retrying since there was some update on requestId by some other thread");
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
LOG.warn("Unexpected InterruptException occurred while trying to get requestId");
}
return getAndIncrementRequestId(companyId, retry - 1);
}
company.setRequestId(requestId); //--------------------------> PROBLEM DOES NOT EXISTS
return company;
}
Sp my question why are there two queries when I have not even passed the entity Company anywhere..?
It is because when you do "companyRepository.findById(companyId);" the returned company is returned in managed state.
So , when in case 1 you set the request id before invoking "companyRepository.updateRequestId(companyId, requestId, oldRequestId);", a transaction object is created in the company repository which executes all the pending updates of the managed entity plus the query of the method "updateRequestId" also gets fired.
While in second case, since you have written set statement after invoking "companyRepository.updateRequestId(companyId, requestId, oldRequestId);", that is why the update on managed object never gets fired because it does not get any transaction

Data doesn't retrieving with Hibernate max query

I'm using Hibernate 4.2.6 with Java DB
Here's my
RegisterationHelper.java
org.hibernate.Transaction tx = session.beginTransaction();
String uid = std.getUserid();
System.out.println(uid);
Query query = session.createQuery("FROM university.Student");
List<Student> student = query.list();
for(Iterator it= student.iterator(); it.hasNext();)
{
//some code....
{
try
{
tx = session.beginTransaction();
int rgstnum=0;
Query q = session.createQuery("Select max(registrationnumber)from Student");
List currentRegNo = q.list();
rgstnum=(Integer)currentRegNo.get(0)+1;
std.setRegistrationnumber(rgstnum);
sc.setRegistrationnumber(rgstnum);
Serializable objID=session.save(std);
session.saveOrUpdate(sc);
tx.commit();
}
catch(Exception e)
{
}
//priniting sc.getRegistrationnumber() showing null
//priniting sc.getCurseid() has data
and RegistrationForm.java
#ManagedBean
#RequestScoped
public class RegistrationForm {
public String submitAction() {
RegistrationHelper rghp = new RegistrationHelper();
Student std = new Student();
std.setFirstname(getFirstName().toString());
std.setLastname(getLastName().toString());
std.setGender(getGender().toString());
std.setDob(getDateofBirth());
std.setAddress(getAddress().toString());
std.setPhone(getContactNumber().toString());
std.setEmail(getEmailID().toString());
std.setUserid(getUserID().toString());
std.setPassword(getPassword().toString());
Studentcourse sc = new Studentcourse();
sc.setCourseid(getCourse().toString());
String msg = rghp.insertStudent(std, sc);
if(msg.equals("error"))
{
setUserIdError("User Id already exist");
setUserID("");
return "Registration";
}
else
{
return "Success";
}
}`
So I think there is problem only with query Query q = session.createQuery("Select max(registrationnumber)from Student"); that doesn't retrieving registrationumber cause I'm able to store data in Student table if removing code regarding StudentCourse and other thing is getting Info: nested transactions not supported in sever log.
So please if my query is wrong or something else.
I do not think there are problems in the query: the message nested transactions not supported refers to the fact that you open the transaction (session.beginTransaction()) twice, one at the beginning and then again within the cycle. Try to remove the second.

Cassandra retrieving data through a thread pool

I am relatively new to Cassandra, I am trying to retrieve data using prepared statement executed via an Executor Pool. Looks like the data I am receiving is not consistent.
I have this user_connections table, where user_id is the row key, friends_id list as a set column.
I have this another table, friends_info table, where friend_id is the row key and all other information as columns.
When am trying to retrieve friends list for user AA, I am retrieving the friends list BBB, CCC, DDD. Which is perfectly fine.
When am trying to retrieve BBB, CCC, DDD via an executor pool using prepared statement. Data is inconsistent. Some times all three records are BBB, Some times all three records are, Some times two records are BBB and one is CCC etc...
I have provided the methods and relevant classes that I am using, can you please help me with this. I know prepared statement is thread safe and expected to work as expected.
public Set<User> listUserConnections(String userId) {
Session session = client.getSession();
Set<String> listUserConnectionIds = listUserConnections(userId, session);
if (listUserConnectionIds.size() == 0)
return new HashSet<User>();
Set<User> listConnectionUserDetails = retrieveUserConnectionProfileInfo(
listUserConnectionIds, session);
return listConnectionUserDetails;
}
private Set<User> retrieveUserConnectionProfileInfo(Set<String> listUserConnectionIds,
Session session) {
Set<Callable<User>> callables = new HashSet<Callable<User>>();
for(String key:listUserConnectionIds){
logger.info("about to add callable" + key);
Callable<User> callable = new QueryTask(key);
callables.add(callable);
}
// invoke in parallel
List<Future<User>> futures;
Set<User> users = new HashSet<User>();
// TODO Revisit this
ExecutorService executorPool = Executors.newFixedThreadPool(100);
try {
futures = executorPool.invokeAll(callables);
for (Future<User> f : futures) {
User user = f.get();
users.add(user);
logger.info("User from future"+user.getUserId());
}
} catch (ExecutionException e) {
logger.error("Error in retrieving the stores in parallel ", e);
} catch (InterruptedException e) {
logger.error("Error in retrieving the stores in parallel as it was interrupted ", e);
} finally {
executorPool.shutdown();
}
return users;
}
//Executor Pool Class
class QueryTask implements Callable<User> {
private String userName;
// final PreparedStatement statement =
// client.getSession().prepare(QueryConstants.GET_ALL_STORE_BRANDS);
QueryTask(String name) {
this.userName = name;
}
#Override
public User call() throws Exception {
// -------------I am seeing the userName is correct------------- for example BBB
logger.info("inside call processing queries for " + userName);
//------------This is a prepared statement, userPreparedStatement.getbStUserInfo()
BoundStatement bStUserInfo = userPreparedStatement.getbStUserInfo();
bStUserInfo.bind(userName);
Session session = client.getSession();
ResultSet rs = session.execute(bStUserInfo);
User user = new User();
Iterator<Row> rowIterator = rs.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
//-------This user id is not right
logger.info("Inside the callable after retrieval"+row.getString(TableConstants.Users.COLUMN_NAME_USER_ID));
user.setUserId(row.getString(TableConstants.Users.COLUMN_NAME_USER_ID));
return user;
}
logger.info("outside the while loop");
return user;
}
}
Thank you so much #Ralf and Alex Popescu for getting back to me on this. Datastax had a documentation that dives deep on how the Aync calls work.
# Alex Popescu. Thanks I tried their aync calls and it worked fine for me.

Projection Queries: How to load raw String using JPA for new Entity in AppEngine?

How do I load a list of Strings for a brand new, empty, non-existent table in AppEngine? I tried to follow this example:
http://www.objectdb.com/java/jpa/query/jpql/select#Projection_of_Path_Expressions_
but it gives me an error:
Caused by: javax.persistence.PersistenceException: Class AdminUser for query has not been resolved. Check the query and any imports/aliases specification
Caused by: org.datanucleus.exceptions.ClassNotResolvedException: Class AdminUser for query has not been resolved. Check the query and any imports/aliases specification
Here is the code:
public java.util.List<String> getAdmin() {
EntityManager em = EMF.get().createEntityManager();
try {
TypedQuery<String> tq = em.createQuery("select au.email from AdminUser as au", String.class);
return tq.getResultList(); ///// <=== EXCEPTION
I don't actually want to use an AdminUser class. I only want the single column of Strings. It is not obvious how to create a new empty table on AppEngine.
GAE Datastore is a schemaless NoSQL database. There are no tables. Only entities that must have a kind, an id and can have an arbitrary set of properties.
You can use Datastore via JPA API, to give you nice typed Java classes instead of low-level untyped entities.
AppEngine does not support JPA raw primitive queries as in the example link. I had to use the DatastoreService API directly. Here is what I tried. Needs some cleaning as many of the things did not work, but this did.
public java.util.List<String> getAdmin() {
log.info("getAdmin()");
// AppEngine does not support strong consistency... will frequently return stale results. Setting read policy won't work.
// Construct a read policy for strong consistency
ReadPolicy policy = new ReadPolicy(ReadPolicy.Consistency.STRONG);
// Set the read policy
DatastoreServiceConfig consistentConfig = DatastoreServiceConfig.Builder.withReadPolicy(policy);
// Get Datastore service with the given configuration
DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService(consistentConfig);
com.google.appengine.api.datastore.Query query = new com.google.appengine.api.datastore.Query("AdminUser");
// DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
java.util.List<Entity> events = datastoreService.prepare(query).asList(FetchOptions.Builder.withDefaults());
ArrayList<String> al = new ArrayList<String>();
for(Entity entity: events) {
String s = entity.getProperty("email").toString();
al.add(s);
}
if(true) return al;
#SuppressWarnings("unused")
EntityManager em = EMF.get().createEntityManager();
try {
TypedQuery<String> tq = em.createQuery("select au.email from AdminUser as au", String.class);
return tq.getResultList();
} catch (ClassNotResolvedException | javax.persistence.PersistenceException cnre) {
// catch the exception because AppEngine DataStore has no way to create a new empty Entity table.
log.warning("AdminUser entity does not exist or is empty.");
return new java.util.ArrayList<String>();
} finally {
em.close();
}
// log.info("getAdmin(): al.size(): " + al.size());
}
public void setAdmin(java.util.List<String> admin) {
log.info("setAdmin(), admin.size():"+admin.size());
// delete all AdminUsers
com.google.appengine.api.datastore.Query query = new com.google.appengine.api.datastore.Query("AdminUser");
DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
java.util.List<Entity> events = datastoreService.prepare(query).asList(FetchOptions.Builder.withDefaults());
for(Entity entity: events) {
datastoreService.delete(entity.getKey());
}
// EntityManager em = EMF.get().createEntityManager();
// Query q = em.createQuery("delete from AdminUser");
// q.executeUpdate();
// DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
for (String s: admin) {
log.info("creating AdminUser Entity...");
Entity e = new Entity("AdminUser");
e.setProperty("email", s);
datastoreService.put(e);
}
// Must wait for Datastore to actually write records. Ignores consistency even with strong consistency set.
// this doesn't even work sometimes...
//try { Thread.sleep(5000); } catch (InterruptedException e) {}
// EntityManager em = EMF.get().createEntityManager();
// for (String s: admin) {
// Entity e = new Entity("AdminUser");
// e.setProperty("email", s);
// em.persist(e);
// }
// em.close();
} // setAdmin()

Categories

Resources