views:

78

answers:

2

I am trying to execute the following JPA query:

    public static final String UPDATE_INVENTORY_CUSTOMER_FOR_AMS_MAPPING = "UPDATE Inventory inventory SET" 
    + " inventory.customer.id = :" + DataAccessConstants.PARAM_CUSTOMER_ID
    + " ,inventory.lastUpdateUserId = :" + DataAccessConstants.PARAM_USER_ID
    + " where inventory.amsConsignorName = :" + DataAccessConstants.PARAM_AMS_CONSIGNOR_NAME
    + " and inventory.amsConsignorOrgCd = :" + DataAccessConstants.PARAM_AMS_CONSIGNOR_ORG_CD
    + " and inventory.amsConsignorTypeName = :" + DataAccessConstants.PARAM_AMS_CONSIGNOR_TYPE
    + " and inventory.status.code in (:" + DataAccessConstants.PARAM_STATUS + ")";  

but it is seeing the following:

update ATL_INVENTORY,  set CONSIGNOR_ID=?, LAST_UPDATE_USER_ID=? where AMS_CONSIGNOR_NAME=? and AMS_CONSIGNOR_ORG_CD=? and AMS_CONSIGNOR_TYPE_NAME=? and (CODE in (? , ? , ? , ?))

Any ideal as to why there is a comma after the table name?


Solution

I had to change the original query to the following:

update Inventory inv set " 
    + "inv.customer.id = :" + DataAccessConstants.PARAM_CUSTOMER_ID + " "
    + "where inv.amsConsignorName =:" + DataAccessConstants.PARAM_AMS_CONSIGNOR_NAME + " "
    + "and inv.amsConsignorOrgCd =:" + DataAccessConstants.PARAM_AMS_CONSIGNOR_ORG_CD + " "
    + "and inv.amsConsignorTypeName =:" + DataAccessConstants.PARAM_AMS_CONSIGNOR_TYPE + " "
    + "and exists(select 1 from Code code where inv.status = code and code.code in (:" + DataAccessConstants.PARAM_STATUS + "))

Which then produced this:

update ATL_INVENTORY set CONSIGNOR_ID=? where AMS_CONSIGNOR_NAME=? and AMS_CONSIGNOR_ORG_CD=? and AMS_CONSIGNOR_TYPE_NAME=? and (exists (select 1 from ATL_CODE code1_ where ATL_INVENTORY.STATUS=CODE_ID and (code1_.CODE in (? , ? , ? , ?))))

Based on a clarification located here: Incorrect SQL generated for JPA QL Update statement involving multiple entities

+1  A: 

Your query is code as UPDATE Inventory inventory SET, but the generated SQL says update ATL_INVENTORY, set. Why is the literal SQL string not what you coded? When I encounter mysteries like this, they're usually caused by assuming that one thing is being done when in fact another is in play.

This suggests that the SQL you coded isn't being used to generate that SQL the way you're assuming. See where else this query might be coming from. I'd bet that the real source has a misplaced comma in it.

Which JPA implementation are you using? If I'm incorrect about a bad assumption, it says that there's a bug in the implementation. Have you used it before? Have you had success with UPDATE? If yes, it's definitely buried somewhere in your code base.

You have an interface with a bunch of constants in it. Personally, I don't care for a design like that. It's an anti-pattern with a name.

duffymo
Thanks - on the question "you have an interface with a bunch of constants in it" that is incorrect. Just a simple class with static named quires in it.
boyd4715
I don't like that much, either. Why wouldn't you put the constants in the class that uses them?
duffymo
It was suggested on this site that if you have a lot of named queries that you place them in a constants file separately. The pojo then just makes a reference to them. This way with constants, no chance of misspelling and I think it is cleaner.
boyd4715
I disagree. The issue isn't constants; it's the "separate" part that I don't like. If you write a DAO that needs constants, by all means encapsulate them in the DAO code. Why put them somewhere else? They can even be private if they are static final constants in the class that uses them.
duffymo
Well, like a lot of things are are many ways to skin the cat. I like the separation - putting this into the DAO class just clutters it up.
boyd4715
It's your funeral...seems to go against the idea of encapsulation and loose coupling to me. So if that's an abstract class that others presumably extend, all the subclasses have access to constants that should only be available to the one DAO? Wrong. It's worth the "clutter" to keep things together that belong together. Get an IDE that lets you open and close method bodies if the clutter is bothering you.
duffymo
Have you considered using @NamedQueries instead of constants? They get evaluated and cached when your persistence provider starts. Keeping these queries in the source file of the entity they belong to is also good practice imo.
Willi
Duffymo - It's your funeral...seems to go against the idea of encapsulation and loose coupling to me - isnt the name of the game to be loosely coupled - not sure what you mean by its your funeral. I think you miss understand, the named queries just sit in a simple class file that has a bunch of constants. Using the @NameQueries with these constants works great. We have a Data Service layer to separate business logic from Data Access Logic. This allow business logic to access the database very easy with out dealing with the dao.
boyd4715
Yes, the name of the game is to be loosely coupled. If you don't have to go out to a class to get your constants, because you already have them as part of your own class definition, that means one less class to be coupled to. I'm not misunderstanding anything. I'm sure it "works". I think you fail to understand what coupling is if you can't see that requiring your DAO to go outside itself to get constants that could be packaged within increases the number of classes in that graph by one.
duffymo
I understand completely. I think that this thread has deviated from the original question. For Queries that the DAO class needs to use, the queries are part of the class. For Named queries which require no other logic then what is in the query itself are being sent directly to the jpatemplate - using a data service frame work - not stopping in any custom DAO class - those queries are located in a separate file.
boyd4715
+1  A: 

A bug in the JPA provider is very unlikely in my opinion so, as @duffymo said, are you sure you're using the right constant, that the code or maybe dependencies are up-to-date? I'd dig in that direction.

That being said, I really wonder why you're not using named queries (that are most of time pre-compiled by the persistence implementation at deployment time), either in the Java code or in meta-data mapping files (the fun part is that people didn't find having EJB-QL queries externalized in XML very manageable in EJB 2.x, hence the @NamedQuery annotation of JPA).

Pascal Thivent
As stated we are using @NameQuery. Just happens that I have placed the named queries in a separate file in the same package. We have a data service layer which allow us to pass these name queries to the data layer. Using constants for the named queries prevents any issue for the business layer developers on which query to access.
boyd4715