How to do cascade save or update using hql query in hibernate? also how can i use cascade update for some specific fields instead of updating all child table fields?
for example table User has
userName varchar(10)
Password varchar(10)
table UserAccessRights has
username varchar(10) FK of User table
password varchar(10) FK of User table
Authpassword varchar(10)
cascade update should happen only for username not for password. how can i acheive this?
You don't.
Since the cascade is a Hibernate configuration matter (i.e. HBM or annotations) the data must be returned to Java for processing of cascades. Doing UPDATE/DELETE row modifications in HQL happens entirely on the SQL server (and the SQL server does not understand JPA cascades, as JPA is a Java API not an SQL API or SQL standard).
You need to specify your cascade setting in your hbm files I suppose.
<set name="columnrecord" cascade="save-update" table="..."...>
<key>
<column name="COLUMN_NAME" not-null="true" />
</key>
<one-to-many class="..." />
</set>
Related
I have id column with generated strategy AUTO, I'm wondering, why MySql generate hibernate_sequence table? I supposed that hibernate will pick IDENTITY id generating strategy
<mapped-superclass class="com.cl.xlp.model.data.Identity">
<attributes>
<id name="id">
<column name="id" />
<generated-value strategy="AUTO" />
</id>
</attributes>
</mapped-superclass>
Hibernate properties
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.hbm2ddl.auto=update
Mysql connector version
version.mysql.connector>5.1.39</version.mysql.connector>
Mysql server version is 5.6.12
The way Hibernate interprets AUTO generation type has changed starting with Hibernate version 5.0.
When using Hibernate v 4.0 and Generation Type as AUTO, specifically for MySql, Hibernate would choose the IDENTITY strategy (and thus use the AUTO_INCREMENT feature) for generating IDs for the table in question.
Starting with version 5.0 when Generation Type is selected as AUTO, Hibernate uses SequenceStyleGenerator regardless of the database. In case of MySql Hibernate emulates a sequence using a table and is why you are seeing the hibernate_sequence table. MySql doesn't support the standard sequence type natively.
References
http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators-auto
https://www.thoughts-on-java.org/5-things-you-need-to-know-when-using-hibernate-with-mysql/
If you use strategy="AUTO", Hibernate will generate a table called hibernate_sequence to provide the next number for the ID sequence. You may have forgotten to add the AutoIncrement feature to your table's PK.
You may use generation strategy strategy="IDENTITY" to enforce using the AutoIncrement feature available in MySql and avoid creating a table.
I am working on an enterprise application where we use Hibernate and a many-to-many relationship with a join table. We are seeing very sporadic database deadlocks in production (with high volume) that we cannot recreate.
Category.java
public class Category {
....
private Set<Product> products = new HashSet<Product>();
...
}
Category.hbm.xml
<class
name="Category"
table="CATEGORY"
>
...
<!-- uni-directional many-to-many association to Product -->
<set
name="products"
table="CATEGORY_PRODUCT_ASSC"
lazy="false"
cascade="none"
>
<key column="CATEGORY_ID" />
<many-to-many class="Product" column="PRODUCT_ID" />
</set>
</class>
Product.java, Product.hbm.xml do not have a set of Categories, as this is uni-directional many-to-many
The CATEGORY_PRODUCT_ASSC table is a simple join table that only has 2 columns: CATEGORY_ID and PRODUCT_ID.
Right now, we are calling Session.saveOrUpdate on the Category instance object for the sole purpose of getting the inserts in the CATEGORY_PRODUCT_ASSC join table (nothing changed on the Category)
I turn on Hibernate show_sql and see the following:
update CATEGORY set NAME=?, DESCRIPTION=?, where category_id=?
insert into CATEGORY_PRODUCT_ASSC (CATEGORY_ID, PRODUCT_ID) values (?, ?)
The problem is that we have many products being created at the exact same second on multiple servers, all for the same Category.
When we see deadlocks, the update CATEGORY call is inevitably involved. We need to prevent these update CATEGORY SQL statements from being executed.
Option 1: Is there any way that I can call Session.saveOrUpdate(category) and have it not update Category (since that has not changed), but still do the insert into the join table CATEGORY_PRODUCT_ASSC ?
Option 2: If not, we have thought about just doing a straight INSERT of the CATEGORY_PRODUCT_ASSC rows via JDBC. However, one concern is stale Hibernate objects (Category objects) in the cache. Any ideas/recommendations on this possible approach?
Thank you very much in advance for your help. :-)
We resolved this issue. It did turn out to be the update category statement. Instead of using the CATEGORY_PRODUCT_ASSC table as a join-through for the many-to-many relationship, we created a Hibernate-managed entity that represents this join table ... CategoryProductAssc.
This way, we could directly persist the relationship without having to call Session.saveOrUpdate on the Category instance object for the sole purpose of getting the inserts in the CATEGORY_PRODUCT_ASSC join table when nothing changed on the Category object.
I created Cactus tests that spun up 20 simultaneous executions, tested old vs new code and our DBAs monitored and saw concurrency with the old code and no concurrency with the new code.
An app I'm working on is using Oracle and Hibernate as ORM. When I'm trying to insert PartyUserObject I keep getting following errors:
could not insert: [Person]; SQL [insert into PARTY (............)]; constraint [PARTY_FK1]
java.sql.SQLIntegrityConstraintViolationException: ORA-02291: integrity constraint (PARTY_FK1) violated - parent key not found
The message seems to be obvious, but I can't configure Hibernate to get it working.
Relevant entities' relations and hbm.xml files are as follows:
PartyUser.java
private Party ap;
Party.java
private Address address;
private Set<PartyUser> partyUsers;
PartyUser.hbm.xml
<many-to-one
name="ap"
column="AP_ID"
class="Party"
not-null="true"
lazy="false"
cascade="save-update,evict">
</many-to-one>
Party.hbm.xml
<set name="partyUsers" inverse="true" fetch="subselect">
<key column="AP_ID"/>
<one-to-many class="PartyUser"/>
</set>
PARTY_FK1 refers to address FK in the party table. As I said before save is called on the DAO for a newly instantiated PartyUser object (associated Party and Address objects are new as well). All ids are generated on the java side. As you probably noticed both entities has cascade turned on.
Any ideas what's wrong?
I am not sure as to why this happens, but I see this error all the time. What I have been doing is at the beginning, when I add all of my data, first I turn off constraints with: SET DATABASE REFERENTIAL INTEGRITY FALSE and then at the end I just turn it back on SET DATABASE REFERENTIAL INTEGRITY TRUE. Not so much a fix, as it is a hack, but it works for us so I thought I would share the knowledge.
FYI, it turned out that hibernate was configured to use db sequence generation, but ids in turn were preassigned in the java code. fmdl
Is there a way to tell Hibernate to wrap a column in a to_char when using it to join to another table or conversely convert a NUMBER to a VARCHAR? I have a situation where I have a table which contains a generic key column of type VARCHAR which stores the Id of another table which is a Number. I am getting a SQL exception when Hibernate executes the SQL it generates which uses '=' to compare the two columns.
Thanks...
P.S. I know this is not ideal but I am stuck with the schema so I have to deal with it.
This should be possible using a formula in your many-to-one. From section 5.1.22. Column and formula elements (solution also mentioned in this previous answer):
column and formula attributes can
even be combined within the same
property or association mapping to
express, for example, exotic join
conditions.
<many-to-one name="homeAddress" class="Address"
insert="false" update="false">
<column name="person_id" not-null="true" length="10"/>
<formula>'MAILING'</formula>
</many-to-one>
With annotations (if you are using Hibernate 3.5.0-Beta-2+, see HHH-4382):
#ManyToOne
#Formula(value="( select v_pipe_offerprice.offerprice_fk from v_pipe_offerprice where v_pipe_offerprice.id = id )")
public OfferPrice getOfferPrice() { return offerPrice; }
Or maybe check the #JoinColumnsOrFormula:
#ManyToOne
#JoinColumnsOrFormulas(
{ #JoinColumnOrFormula(formula=#JoinFormula(value="SUBSTR(product_idnf, 1, 3)", referencedColumnName="product_idnf")) })
#Fetch(FetchMode.JOIN)
private Product productFamily;
I have the following two table (which are tied in with Spring security - but the issue I believe is with Hibernate):
Table user
Table authority
The user table is tied (through Hibernate) to a domain object in my application: class User, which has the following attributes (and corresponding getters and setters), which correspond to columns in the user table (except for the Collection which is explained later):
long uId
String username
String password
...
Collection<GrantedAuthority> authorities
The authority table has 2 columns: UserId (foreign key into user table), and Authority (e.g. "ROLE_USER"). This table is NOT represented as a domain object, but is simply a collection in the User class.
To create the mapping, in my .hbm file I use the following:
<class name="com.business.project.domain.User" table="user">
<id name="uId" column="UserId"></id>
<property name="username" column="Name" type="java.lang.String" />
<property name="password" column="Password" type="java.lang.String" />
...
<set name="authorities" table="authority">
<key column="UserId" />
<element column="Authority" type="java.lang.String" />
</set>
</class>
In my hibernate DAO implementation, I create a query object, execute the query, and cast the result to a User object:
...
Query query = session.createQuery("from User where name = :username");
...
User user = (User) query.uniqueResult();
At this point, I would expect this object to be populated with the data that it pulled from the DB (I made sure that the tables are populated properly with test data and the mapping names are correct in the mapping file).
However, calling the getter methods for various attributes on the user object all return NULL for some reason. Can somebody see something immediately wrong with my setup? Perhaps I mapped the collection (to foreign key relationship) wrong? THANKS!
Update: here is the sql query that hibernate generated (taken from its DEBUG output):
Hibernate: select user0_.UserId as UserId1_, user0_.Name as Name1_,
user0_.Password as Password1_ from user user0_ where user0_.Name=?
For some reason, it doesn't show anything related to the authority table...does this mean that my mapping is incorrect?
Edit: Per bozho's suggestion, I took a look at the messages on the consol on startup (tomcat), but didn't see anything out of the ordinary:
Feb 16, 2010 10:35:12 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: com.me.project.domain.User -> user
Feb 16, 2010 10:35:12 AM org.hibernate.cfg.HbmBinder bindCollection
INFO: Mapping collection: com.me.project.domain.User.authorities -> authority
Query query = session.craeteQuery("FROM User WHERE username = :username");
query.setString("username", "SomeUserName");
That should pretty much do it.
Try with "from User where username = :username"
HQL uses class properties, not db column names
Are you clearing the database everytime you run the test/java code? In hibernate there is a setting and when it is turned on, it can clear the database everytime a test/java code is run.
Can you do a findAll() and print the size? I very much suspect it is the wrong db, or no data in the db or clearing of data.
NOTE: Check for "hibernate.hbm2ddl.auto" property in your config file. If it is set to "create-drop" hibernate will auto create the schema on startup and delete the schema when VM shuts down. Just point it to "update" or something
http://docs.atlassian.com/hibernate2/2.1.8/reference/session-configuration.html
"Password" usually is a keyword in databases. It seems like you're hitting a name collision problem. Try the following. Put tick mark around the column name for escaping.
<property name="username" column="`Name`" type="java.lang.String" />
<property name="password" column="`Password`" type="java.lang.String" />
Assume you're using org.springframework.security.GrantedAuthority, then your mapping for authorities is incorrect. Based on the way you're mapping, when you access the collection, you most likely will get a ClassCastException. You probably want to use something like UerType to avoid the problem.