Caused by: org.hibernate.hql.ast.QuerySyntaxException: unexpected end of subtree [select count(*) from com.test.Fruits as fruit where fruit.fruitId in () order by fruit.fruitName desc ]
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:31)
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:24)
at org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:59)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:235)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:160)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1113)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at com.test.FruitDAOServiceImpl.fruitCount(FruitDAOServiceImpl.java:682)
at jrockit.reflect.VirtualNativeMethodInvoker.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;(Unknown Source)
at java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;I)Ljava.lang.Object;(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:139)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
While there could be many reasons because of which this error comes. For me, the problem was that the parameter list I was passing was empty.
I was getting all the fruits for which fruit id is in the fruitIdList I was passing as the query parameter. If the fruitIdList is emply list then this problem comes. I solved it by conditionally framing query based on the list. That is instead of
public Long fruitCount(List fruitIdList){
........
Query fruitQuery = getSession().createQuery("select count(*) from com.test.Fruits as fruit where fruit.fruitId in (:fruitIdList) order by fruit.fruitName desc ");
fruitQuery.setParameterList("fruitIdList", fruitIdList);
List fruitCountList = fruitQuery.list();
..........
}
I did this
public Long fruitCount(List fruitIdList){
........
StringBuffer queryString = new StringBuffer("select count(*) from com.test.Fruits as fruit ");
if(fruitIdList !=null && !fruitIdList.isEmpty()){
queryString.append(" where fruit.fruitId in (:fruitIdList) ");
}
queryString.append(" order by fruit.fruitName desc ");
Query fruitQuery = getSession().createQuery(queryString.toString());
if(fruitIdList !=null && !fruitIdList.isEmpty()){
fruitQuery.setParameterList("fruitIdList", fruitIdList);
}
List fruitCountList = fruitQuery.list();
..........
}
In short, append the collection parameter in the query and the query parameter only if the collection is non-empty.
This is how I setup JCaptcha in my application. Following code snippet is for the test page I have created to test the JCaptcha and Spring integration
1) First create a controller which will generate a new Captcha for each session based on session id
package com.example.web.controller;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.example.domain.LoginCommand;
import com.example.logger.LoginLogger;
public class CaptchaController extends LoginBaseController {
public CaptchaController(){
setCommandClass(LoginCommand.class);
}
@Override
protected ModelAndView showForm(HttpServletRequest request, HttpServletResponse response, BindException errors,
Map controlModel) throws Exception {
byte[] captchaChallengeAsJpeg = null;
// the output stream to render the captcha image as jpeg into
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
// get the session id that will identify the generated captcha.
//the same id must be used to validate the response, the session id is a good candidate!
String captchaId = request.getSession().getId();
LoginLogger.debug(this, "Captcha ID which gave the image::" + captchaId);
// call the ImageCaptchaService getChallenge method
BufferedImage challenge = ((ImageCaptchaService)getCaptchaService()).getImageChallengeForID(captchaId, request.getLocale());
// a jpeg encoder
JPEGImageEncoder jpegEncoder =
JPEGCodec.createJPEGEncoder(jpegOutputStream);
jpegEncoder.encode(challenge);
} catch (IllegalArgumentException e) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return null;
} catch (CaptchaServiceException e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return null;
}
captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
// flush it in the response
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
//response.setContentType("image/jpeg");
// response.getOutputStream().write(jpegOutputStream);
ServletOutputStream responseOutputStream =
response.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
return null;
}
}
Please note that your implementation can vary. The only thing you want is a simple Servlet which will execute the code in showForm method above. In my case I am relying on Spring framework to execute this code because in the JSP where you show Captcha image I have written something like this
<img id=”captchaImage” src=”http://localhost:8080/LoginApplication/captcha.htm”>. In my application the URL captcha.htm is wired to this controller. But you can choose to have a simple servlet mapped instead of a Spring Controller.
2) Make the following entries in your Spring config files to configure JCaptcha
toddlist4050Arial0103001003502550000180180000
For test purpose I have used a Simple Text Captcha.
3) To test create a command,controller and JSP like this
public class LoginCommand implements Serializable {
private String verificationTextForForgotPass;
//getter and setter methods
}
package com.example.web.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import com.octo.captcha.service.CaptchaServiceException;
import com.example.domain.LoginCommand;
public class CaptchaDemoController extends LoginBaseController {
private CaptchaService captchaService;
//Getter and setter for captchaService
public CaptchaDemoController() {
setCommandClass(LoginCommand.class);
}
@Override
protected Object formBackingObject(HttpServletRequest request) throws Exception {
LoginCommand command = new LoginCommand();
return command;
}
@Override
protected ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response,
Object command, BindException errors) throws Exception {
boolean isResponseCorrect = false;
String sessionId = request.getSession().getId();
//retrieve the response
String verificationText = ((LoginCommand) command).getVerificationTextForForgotPass();
// Call the Service method
try {
isResponseCorrect = getCaptchaService().validateResponseForID(sessionId, verificationText);
}
catch (CaptchaServiceException e) {
//should not happen, may be thrown if the id is not valid
}
//You can do whatever you want to based on the response
response.getWriter().write(String.valueOf(isResponseCorrect));
return null;
}
}
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
Enter the text here
As you can see the JSP will just show one Captcha Image and a text box where you can enter the Image text. The controller will verify the entered text and display true or false based on the result. You can implement your logic here for the Captcha verification result.
4) Finally make the following entries in your corresponding spring config file
captchaDemoControllercaptchaController
Oops I forgot to mention, you should have JCaptcha jars in your classpath for this example to work
I have written this post using the working code I have. I might have missed some configuration in this post. Let me know if you get any error. I will update the post.
Collection mappings in Hibernate can be configured to sort using a specific comparator.
Consider the following mapping
......
......
In the example above Hibernate will order the bankAccounts set according to their natural order. If the BankAccout class implements Comparable interface, compareTo method will be used to sort the Set.
What if you want to sort the set differently? What if you want to use a comparator to sort the set.
The sort attribute can have three possible values
The first option is
which sorts by natural order
the second option is
which tells Hibernate that the Set needs not to be sorted
and the third option is
where you specify what comparator should be used to sort the Set.
Let’s see it through code example. For example suppose class BankAccount is defined as below
package com.example;
//import statements
public class BankAccount implements Comparable, Serializable{
private String accountName;
private String accountShortName;
//getter and setter methods
public int compareTo(BankAccount that) {
final int BEFORE = -1;
final int AFTER = 1;
if (that == null) {
return BEFORE;
}
Comparable thisAccountName = this.getAccountName();
Comparable thatAccountName = that.getAccountName();
if(thisAccountName == null) {
return AFTER;
} else if(thatAccountName == null) {
return BEFORE;
} else {
return thisAccountName.compareTo(thatAccountName);
}
}
}
In this case sort=”natural” will sort using the above compareTo method which compares the accountName to sort.
Now suppose you want that for this specific mapping you want the collection to be sorted by, say, accountShortName. You will define a Comparator like this
package com.example;
//import statements
public class BankAccountShortNameComparator implements Comparator{
public int compare(BankAccount o1, BankAccount o2) {
if(o1!=null && o2!=null && o1.getAccountShortName()!=null && o2.getAccountShortName()!=null) {
return o1.getAccountShortName().compareTo(o2.getAccountShortName());
}
if(o1!=null && o2!=null) {
return o1.compareTo(o2);
}
return 0;
}
}
Then your mapping will say something like this
In this way Hibernate will use your custom Comparator to sort the set
This is the simple query which I use to find the primary key of a table. Not a rocket science. But simple and handy.
Inner query version
SELECT TABLE_NAME, COLUMN_NAME PRIMARY_KEY,CONSTRAINT_NAME,OWNER
FROM USER_CONS_COLUMNS UCC WHERE
UCC.CONSTRAINT_NAME=(
SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS UC WHERE UPPER(UC.TABLE_NAME)=UPPER('ADDRESS') AND UC.CONSTRAINT_TYPE='P'
)
Or Join Version
SELECT UCC.TABLE_NAME, UCC.COLUMN_NAME PRIMARY_KEY, UCC.CONSTRAINT_NAME,UCC.OWNER
FROM USER_CONS_COLUMNS UCC,USER_CONSTRAINTS UC
WHERE UCC.CONSTRAINT_NAME= UC.CONSTRAINT_NAME
AND UPPER(UC.TABLE_NAME)=UPPER('ADDRESS')
AND UC.CONSTRAINT_TYPE='P'
Possibly
you are using different set of jars at runtime and compile time. In
case of tomcat you might be using some of the jars. Try adding jars
like el-api.jar, javaee.jar, jstl-1.2.jar from your development
environment to the Tomcat/common/lib folder, one by one and it should
solve the problem
…………………..
some more mapping elements
…………………..
…………………..
<many-to-one name=”bId” class=”com.xxx.B” fetch=”select”>
<column name=”B_ID” precision=”29″ scale=”0″ />
</many-to-one>
…………………..
A is referring to B using a primary key column of bId of B.
In that post I have mentioned that if B is a transient object and you don’t want to persist the value of B to A then just tell the hibernate to ignore that value by saying update=”false” insert=”false” in the many to one mapping.
But what if you want to persist the value of foreign key in A.
Then the approach is different. You have to make sure that instance B is persistent not transient.
That is if your code says something like
A a = new A();
B b = new B();
a.setB(b);
…..
…..
session.save(a);
you are in trouble. Because B is in transient state. You have to attach b to the session.
There may be other ways of attaching this transient object to session. The approach I am following is simple. I am reading the value of B from the database using Hibernate. That way, hibernate attaches B to session and it is then a persistent object.
That is I do something like
A a = new A();
B b = session.get(B.class, new Long(1));
a.setB(b);
…..
…..
session.save(a);
I won’t get any exception because this time there is no transient object to save. All the objects are persistent.
Spring transaction management, Hibernate transaction management in Spring
There was a problem/defect in the MyEclipse tutorial on Hibernate Spring. It was not a major problem. The tutorial demonstrates the Spring and Hibernate functionality pretty well. The only problem was that the code does seems to work properly. Because of absence of proper transaction management in code the data was not getting persisted in the database. Because of the caching in Hibernate it seems to the user that the data is being written to the database and then read back.
There are two solutions to the problem. One is to write the transaction management code in the java class itself. Another is to manage transaction via Spring’s transaction management. The second solution makes more sense because it shows of the Spring’s capability of managing transaction in Hibernate. You can see both the solutions here.
I am writing the Spring’s configuration for Hibernate transaction management again.
I had really a very tough time today while installing MySQL on vista. All the steps in the installation are simple and self-explanatory. I just want to mention two things from my experience
Before starting installation
1) If you want to install MySQL after uninstall your current MySQL fuly and properly. After uninstallation you should manually delete the installation folder at c:\Program Files\MySQL or at any location your MySQL is installed.
2) Turn off UAC(the nasty part of Windows Vista)
3) Turn off Windows Firewall.
4) Restart your PC.
5) Try now. This time the installation should be smooth and easy