how to make a clause in hibernate mapping files? - java

I want to add a (where) condition in hibernate mapping file when fetching,
how could i do that for example fetch="select" where id != 1 ,am not using annotations also, so please specify within the mapping (hbm) files.

According to the Hibernate documentation, you can specify a where clause when mapping a collection:
6.2. Collection mappings
(...) The <map> element is
representative:
<map
name="propertyName" (1)
table="table_name" (2)
schema="schema_name" (3)
lazy="true|extra|false" (4)
inverse="true|false" (5)
cascade="all|none|save-update|delete|all-delete-orphan|delet(6)e-orphan"
sort="unsorted|natural|comparatorClass" (7)
order-by="column_name asc|desc" (8)
where="arbitrary sql where condition" (9)
fetch="join|select|subselect" (10)
batch-size="N" (11)
access="field|property|ClassName" (12)
optimistic-lock="true|false" (13)
mutable="true|false" (14)
node="element-name|."
embed-xml="true|false"
>
<key .... />
<map-key .... />
<element .... />
</map>
(...)
(9) where (optional): specifies an
arbitrary SQL WHERE condition that is
used when retrieving or removing the
collection. This is useful if the
collection needs to contain only a
subset of the available data.
This is also supported at the <class> level.

You could perhaps define a <filter> in the mapping file, and attach it to the class mapping definition. See the docs for examples.

Related

Mapping a map collection containing superclasses in Hibernate

I am trying to map a map collection of String, SuperClass using XML mapping files. Here's what I have:
<map name="mapName" cascade="all-delete-orphan">
<key column="ID" />
<index column="KEY" type="string" />
<one-to-many class="SuperClass" />
</map>
The SuperClass has (currently one but probably going to need some more in the future) a subclass that I'm going to call SubClass. So I have a bunch of SubClass and SuperClass objects in the map and when Hibernate attempts to search for them after adding them I get a
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
I'm pretty sure Hibernate is looking for classes of type SuperType when the objects in the map actually have some SubTypes as well.
Here's the gist of how the mapping was done for the hierarchy in case you need a better representation of what I'm talking about:
<class name="SuperClass" table="SUPER_CLASS">
...properties...
(contains some <component> tags as well if it matters)
<union-subclass name="SubClass" table="SUBCLASS">
...more properties...
</union-subclass>
</class>

Hibernate multi-app environment. Delete one child object if parent has multiple children

Hibernate 4.1 with XML mappings, Struts 1.3, multi-app environment sharing the same database. Let's say we have three tables:
Client Car_Client House_Client
------ ---------- ------------
id client_id client_id
name date_purchased date_purchased
The 3 mapping files:
<hibernate-mapping>
<joined-subclass name="CarClient" extends="Client" table="Car_Client">
<key column="client_id" />
<property name="datePurchased">
<column name="date_purchased" />
</property>
</joined-subclass>
</hibernate-mapping>
<hibernate-mapping>
<joined-subclass name="HouseClient" table="House_Client">
<key column="client_id" />
<property name="datePurchased">
<column name="date_purchased" />
</property>
</joined-subclass>
</hibernate-mapping>
Client is the parent object and the two applications(Car and House) share the parent table but each have their own subclass of the parent table to store extra information about the client. Each Hibernate mapping and Java class is extending the parent object.
So in normal use, when the Car app deletes a CarClient, the parent object is also deleted as usually a client exists in only one app. Sometimes though, a client may exist in both apps. Deleting that client from one app will remove the record from the child table and throw a ConstraintViolationException on the parent table.
Our solution is deleting the child record with an SQL query as HQL would try to delete the parent. We then have to refresh the cache so Hibernate knows the child record no longer exists.
Is there a way in Java to tell Hibernate to only delete the child record? Basically override the built-in behavior that deletes the parent object? Without having to write a custom query? May not be possible but I am curious if I'm missing something.

Hibernate retrieves many-to-one without asking

we have a big problem in our development team.
We are using Hibernate and we have some entities which are related in two transitive one-to-many relations. The main object is a Group which has a list of Property instances, and each Property containing a list of Values.
(The mappings are down ahead)
We have two main problems:
A) When making a HQL Query, Criteria Query or SQLQuery it doesn't matter the conditions applied in JOINs or WHERE clauses, Hibernate always retrieves for us all the underlying objects. For example, if I make a Criteria or SQL getting only the Group objects, Hibernate comes and (lazy or not) gets all the Property and Value instances too. We want to control this. We want to do left joins and get only the properties with no values inside (Hibernate removes these properties with no value)
B) When making the Query, for example, a SQL, it shows in the log the SQL code we want. Everything seems perfect. But after that it brings every instance in the list without applying conditions, getting them only by id, and we can assure this because with lazy="true" we see the "load many-to-one" queries in the log.
Is there something we can do in hibernate config, fetching mode/strategy, the mappings configuration or anywhere? I'm thinking on going on Result transformers now.
I would be grateful if someone coud give me a hint or tell me where to find a solution to this problem. We are confused about how to get this, but it must be a way.
Thanks in advance
Query:
Criteria lstCriterios = this.getSession().createCriteria(CardGroup.class, CARD_GROUP)
.add(Restrictions.eq(ID_CATEGORY, idCategory));
lstCriterios.createAlias("listProperty", "listProperty", CriteriaSpecification.LEFT_JOIN);
if (clusterId != null) {
lstCriterios.add(Restrictions.or(
Restrictions.isNull("listPropertyValue" + ".value"),
Restrictions.and(Restrictions.eq("listPropertyValue" + ".clusterId", clusterId),
Restrictions.eq("listPropertValue" + ".companyWarehouseId", idCompanyWarehouse))));
lstCriterios
.createAlias("listProperty" + "." + "listPropertyValue", "listPropertyValue",
CriteriaSpecification.LEFT_JOIN,
Restrictions.eq("listPropertyValue" + ".clusterId", clusterId));
} else {
lstCriterios.createAlias("listProperty" + ".listPropertyValue", "listPropertyValue",
CriteriaSpecification.LEFT_JOIN);
}
lstCriterios.add(Restrictions.eq(ID_CATEGORY, idCategory));
lstCriterios.add(Restrictions.eq("listProperty" + ".groupId", idGroup));
lstCriterios.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
/*
* Sorting
*/
lstCriterios.addOrder(Order.asc("order"));
lstCriterios.addOrder(Order.asc("listProperty" + ".order"));
lstCriterios.addOrder(Order.asc("listPropertyValue"+ ".clusterId")); // Agrupacion, podrĂ­a ser nulo
lstCriterios.addOrder(Order.asc("listPropertyValue"+ ".propertyId")); // Propiedad
lstCriterios.addOrder(Order.asc("listPropertyValue"+ ".id"));
return lstCriterios.list();
Group mapping:
<list name="listProperty"
table="FICHA_PROPIEDAD" schema="${db2.siglo.schema}"
inverse="false" cascade="all" >
<key column="ID_FICHA_GRUPO" not-null="false" />
<list-index column="ORDEN" base="1"/>
<one-to-many
class="com.company.aslo.appwebsiglo.model.card.property.property.CardProperty" />
</list>
Property mapping:
<bag name="listPropertyValue"
table="FICHA_PROPIEDAD_VALOR" schema="${db2.siglo.schema}"
inverse="false" cascade="all">
<key column="ID_FICHA_PROPIEDAD" not-null="false" />
<one-to-many
class="com.company.aslo.appwebsiglo.model.card.propertyvalue.propertyvalue.CardPropertyValue" />
</bag>
It seems like our model design was bad and we didn't realize that if the DB table FICHA_PROPIEDAD_VALOR has Composite Key we can't map only one of the attributes in the composite key, because it brings us unexpected results.
Because of this and the nested objects, we had also bad implementations of the hashCode() and equals() methods which Hibernate uses.
I had solved this previously with a ResultTransformer getting the rows from a SQLQuery, but we got the Hibernate solution after that refactoring and changing the design of our model.

How to map a Map<Calendar,Boolean> with jpa/hibernate

i've got 2 tables:
Seat(roomID,seatID,...)
SeatState(roomID,seatID,date,state)
i wanna create a seat class and i would like this class to have a Map attribute. does somebody know how to map this thing?
Hibernate supports using 'Map's as collections. If you are using hbm.xml files, you can use the <map> tag for this purpose. Take a look at http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html for a reference. Also Hibernate supports mapping Calendar fields to TIMESTAMP fields.
So if you are using XML, it should be something like
<map name="booking" table="BOOKING">
<key column="BOOKING_ID"/>
<map-key column="BOOKING_DATE" type="calendar"/>
<element column="IS_BOOKED" type="boolean"/>
</map>
Likewise, JPA / Hibernate Annotation alternatives also exist. You need to use #Embeddable to get this done. See http://hwellmann.blogspot.com/2010/07/jpa-20-mapping-map.html for an example.

Help with foreign key mapping in Hibernate (Spring)?

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.

Categories