I am very new to Hibernate. I have MySQL database and mapped pojos. What should I do next? I know little bit LINQ to SQL from .NET, and it generates me List of mapped objects.
So basically, what are my next steps after creating POJOS if I want to have List of them and do CRUD operations upon them and data will be also saved in DB not only in java objects ?
kthx
please see the hibernate document - Chapter 10. Working with objects
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-querying-executing
You can createQuery() or createCriteria() to get a list of your pojos. for example:
List cats = session.createQuery("from Cat").list();
or
List cats = session.createCriteria(Cat.class).list();
To answer your question about the rest of CRUD, once you've got your list of objects, as described by qrtt1, then you can manipulate the objects in the session:
Session session = // obtain session
Transaction tx = session.beginTransaction();
List cats = session.createQuery("from Cat").list();
Cat firstCat = (Cat)cats.get(0);
firstCat.setName("Cooking Fat");
firstCat.setOwner("Richard O'Sullivan");
// etc for other cats in the collection
tx.commit();
session.close();
Any objects that you obtained via the query are "dirty checked" at the tx.commit(); this means that in this case an update statement will be issued for the first cat retrieved from the query.
Related
I'm fetching from database bunch of persons like this:
public List<Object[]> getLimitedBunchOfPersons(Integer limit) {
Criteria criteria = getSession().createCriteria(Person.class, "person")
.setProjection(
Projections.projectionList()
.add(Projections.property("person.personId"), "personId")
)
.createAlias("person.status","status")
.add(Restrictions.eq("status.statusId", 1L))
.addOrder(Order.asc("person.createdOn"));
return criteria.setMaxResults(limit).list();
}
As I needed to speed things up, I only fetched ID's of my entity. Important thing to note is that I'm manipulating with large number of rows and for one query had to use maxResults limitation.
Now my problem is, how to easily update with Hibernate Criteria API in one database query all fetched rows from previously mentioned query?
Plain SQL query would go something like this:
UPDATE PERSON
SET STATUS = 2, CREATED_ON = CURRENT_TIMESTAMP
WHERE STATUS = 1;
It's important to note that update method have to use same order and limit as getLimitedBunchOfPersons() method.
For Single Object it will work as follows after your code
Person per= (Person) criteria.uniqueResult();
per.setCreatedOn("crtBy");
currentSession.merge(per);
Now if comes in list you can iterate list by passing mentioned code in your List iteration
I have a hibernate code which insert a new role to the table as follows:
Staff staff = new Staff(staffDTO);
Session session = sessionManager.getSession();
session.beginTransaction();
session.save(staff);
session.getTransaction().commit();
Staff is defined as entity.
My question is that how can I get the newly generated row id by the database?
Many thanks.
Hibernate is smart enough :).
After you save the Object in database If you see ,the object have the generated id. Check it.
After save done, just inspect the object and see.
How to get which properties were updated after hibernate update?
For example if I got
SomeEntity se = new SomeEntity();
getHibernateTemplate().save(se);
//then in some other method
se.setProp1("some new value");
//then in 3th method
getHibernateTemplate().update(se);
If you tell hibernate to do dynamic update it will know witch properties were changed and update only them. Is there a way to get the ones that were changed or to check is specific property was changed?
Ended up doing native sql query to compare the state in the db with the state in the entity before flush the session.
Query query = session.createSQLQuery(
"select t.someProp1 from someTable t where t.id = :entityId")
.setParameter("entityId", entity.getId());
List result = query.list();
I have a database with 3 tables: Slideshows, MediaItemsInSlideshows and Mediaitems. I am using this database with a jsp site using hibernate.
I would like to be able to delete a slideshow without deleting the mediaitems. The rows in the MediaItemsInSlideshows should be deleted though.
Currently I use the following code to remove the slideshow. When I use this all mediaitems that were used in the slideshow are gone.
Session session = HibernateUtil.getSessionFactory().openSession();
Slideshow s = this.getSlideshowById(id, session);
session.beginTransaction();
session.delete(s);
session.getTransaction().commit();
This is a visual representation of the database:
Deleting A will set the reference to it in B to null which is forbidden by the schema. An alternative to changing the order of deletions would be to add a reverse one-to-many collection in B, with cascaded deletes. Only the deletion of A would than be needed.
(source: Deleting of related objects in hibernate)
I am using hibernate to update 20K products in my database.
As of now I am pulling in the 20K products, looping through them and modifying some properties and then updating the database.
so:
load products
foreach products
session begintransaction
productDao.MakePersistant(p);
session commit();
As of now things are pretty slow compared to your standard jdbc, what can I do to speed things up?
I am sure I am doing something wrong here.
The right place to look at in the documentation for this kind of treatment is the whole Chapter 13. Batch processing.
Here, there are several obvious mistakes in your current approach:
you should not start/commit the transaction for each update.
you should enable JDBC batching and set it to a reasonable number (10-50):
hibernate.jdbc.batch_size 20
you should flush() and then clear() the session at regular intervals (every n records where n is equal to the hibernate.jdbc.batch_size parameter) or it will keep growing and may explode (with an OutOfMemoryException) at some point.
Below, the example given in the section 13.2. Batch updates illustrating this:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
ScrollableResults customers = session.getNamedQuery("GetCustomers")
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
if ( ++count % 20 == 0 ) {
//flush a batch of updates and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
You may also consider using the StatelessSession.
Another option would be to use DML-style operations (in HQL!): UPDATE FROM? EntityName (WHERE where_conditions)?. This the HQL UPDATE example:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
// or String hqlUpdate = "update Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
.setString( "newName", newName )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
Again, refer to the documentation for the details (especially how to deal with the version or timestamp property values using the VERSIONED keyword).
If this is pseudo-code, I'd recommend moving the transaction outside the loop, or at least have a double loop if having all 20K products in a single transaction is too much:
load products
foreach (batch)
{
try
{
session beginTransaction()
foreach (product in batch)
{
product.saveOrUpdate()
}
session commit()
}
catch (Exception e)
{
e.printStackTrace()
session.rollback()
}
}
Also, I'd recommend that you batch your UPDATEs instead of sending each one individually to the database. There's too much network traffic that way. Bundle each chunk into a single batch and send them all at once.
I agree with the answer above about looking at the chapter on batch processing.
I also wanted to add that you should make sure that you only load what is neccessary for the changes that you need to make for the product.
What I mean is, if the product eagerly loads a large number of other objects that are not important for this transaction, you should consider not loading the joined objects - it will speed up the loading of products and depending on their persistance strategy, may also save you time when making the product persistent again.
The fastest possible way to do a batch update would be to convert it to a single SQL statement and execute it as raw sql on the session. Something like
update TABLE set (x=y) where w=z;
Failing that you can try to make less transactions and do updates in batches:
start session
start transaction
products = session.getNamedQuery("GetProducs")
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
count=0;
foreach product
update product
if ( ++count % 20 == 0 ) {
session.flush();
session.clear();
}
}
commit transaction
close session
For more information look at the Hibernate Community Docs