I present to you the translation of the fourth chapter of the official documentation Hibernate .Article translation is relevant for the version Hibernate 4.2.19.FinalNext chapter -
Hibernate Developer Documentation - Chapter V. Locks')
Content4.1. Batch inserts4.2. Batch updates4.3. StatelessSession4.4. Hibernate query language for DML4.4.1. HQL for UPDATE and DELETE4.4.2. HQL syntax for INSERTThe following example demonstrates the anti-pattern of package inserts.
Example 4.1. A naive way to insert 100,000 rows using HibernateSession session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); session.save(customer); } tx.commit(); session.close();
This code will fall with the exception
OutOfMemoryException after processing about 50,000 lines on most systems. The reason is that Hibernate caches all newly created
Customer instances in the session-level cache. There are several ways to avoid this problem.
Before you start working with batch processing, allow it to be used in JDBC. To enable batch processing, enter a value between 10 and 50 in the
hibernate.jdbc.batch_size property.
ImportantHibernate turns off batch inserts at the JDBC level transparently if you use an id generator
If this approach is not acceptable, you can turn off the second-level cache (second-level cache) by setting the
hibernate.cache.use_second_level_cache property to
false4.1. Batch inserts
When you make new objects persistent, use the
flush () and
clear () session methods to control the size of the first-level cache.
Example 4.2. Flushing and clearing the session Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); session.save(customer); if ( i % 20 == 0 ) {
4.2. Batch updates
Use
flush () and
clear () regularly when you extract and modify data. In addition, use the
scroll () method to take advantage of working with database cursors for queries that return a large number of rows.
Example 4.3. Using scroll () 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 ) {
4.3. StatelessSession
StatelessSession is a command-oriented API provided by Hibernate. Use it to stream data to and from the database in the form of detached objects.
The statelessSession does not have an associated persistence context and does not provide most of the high-level semantics.
Features not provided by StatelessSession:- First level cache
- Interactions with the first-level cache or query cache
- Transactional write-behind or automatic checking for modification ( dirty checking )
StatelessSession restrictions:- Operations performed by a StatelessSession are not cascaded down to related entities.
- Collections are ignored.
- Operations carried out through the StatelessSession bypass the event model of Hibernate and its interceptors.
- Due to the lack of a first-level cache, StatelessSessions are vulnerable to the effects of multiple data aliases ( data aliasing effect s).
- Session StatelessSession - low-level abstraction, which is closer to the underlying JDBC.
Example 4.4. Using StatelessSession StatelessSession session = sessionFactory.openStatelessSession(); Transaction tx = session.beginTransaction(); ScrollableResults customers = session.getNamedQuery("GetCustomers") .scroll(ScrollMode.FORWARD_ONLY); while ( customers.next() ) { Customer customer = (Customer) customers.get(0); customer.updateStuff(...); session.update(customer); } tx.commit(); session.close();
The
Customer objects returned by the request will be disconnected immediately. They will not be associated with any persistence context.
The
insert () ,
update () , and
delete () operations defined in the
StatelessSession interface work directly with table rows. They lead to the immediate execution of the corresponding SQL operations, since they have different semantics than the
save () ,
saveOrUpdate () , and
delete () methods defined in the Session interface.
4.4. Hibernate query language for DML
DML, or
Data Markup Language , is related to SQL expressions such as INSERT, UPDATE, and DELETE. Hibernate provides methods for group execution of SQL-like DML operations, in the form of HQL (
Hibernate Query Language ).
4.4.1 HQL for UPDATE and DELETE
Example 4.5. Pseudo-syntax for UPDATE and DELETE expressions using HQL ( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)?
Suffix? means optional parameter. FROM and WHERE are both optional.
FROM can only point to one entity that can have an alias. If the entity name has an alias, any references to the properties must be qualified by this alias. If the entity name does not have a pseudonym, then the references should not be limited (qualified).
Join'y, implicit or explicit, are prohibited in group HQL-queries. You can use subqueries in the WHERE clause, and the subqueries themselves can contain joines.
Example 4.6. Execute HQL UPDATE using the Query.executeUpdate () method Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
In accordance with the EJB3 specification, HQL UPDATE expressions, by default, do not affect the values ββof the version or the timestamp of modified entities. You can use a versioned update to force Hibernate to reset a version or a timestamp by adding the VERSIONED keyword after UPDATE.
Example 4.7. Update timestamp version Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName"; int updatedEntities = session.createQuery( hqlUpdate ) .setString( "newName", newName ) .setString( "oldName", oldName ) .executeUpdate(); tx.commit(); session.close();
ImportantIf you use a VERSIONED expression, you cannot use custom version types that use the org.hibernate.usertype.UserVersionType class
Example 4.8. HQL DELETE Expression Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlDelete = "delete Customer c where c.name = :oldName";
The
Query.executeUpdate () method returns an
int value that indicates the number of entities affected by the operation. This number does not have to be correlated with the number of rows updated in the database. A group operation in HQL can be several SQL expressions, for example for a joined subclass (joined-subclass). In the example with the subclass to be joined, the DELETE for one of the subclasses may actually result in deletions in the tables under the join or lower in the inheritance hierarchy.
4.4.2 HQL syntax for INSERT
Example 4.9. Pseudo-syntax for INSERT statements INSERT INTO EntityName properties_list select_statement
Only the form INSERT INTO ... SELECT ... is supported. You cannot specify explicit values ββto insert.
properties_list is the equivalent for specifying columns in an INSERT SQL statement. For entities involved in mapping
inheritance , you can specify properties that are directly specified in the class itself, but not from subclasses or the parent class. In other words, an INSERT expression is not polymorphic in its essence.
The select_statement can be any valid HQL select query, but the return types must match the types expected by INSERT. Hibernate checks the returned types at compile time, without waiting for the DBMS to check them. Problems can come from Hibernate types, which are more likely equivalent, but not equal. One example of this is the mismatch of the property defined as org.hibernate.type.DateType and the property defined as org.hibernate.type.TimestampType, even if the database does not differentiate between them, or is capable of doing type conversion itself.
If the
id property is not specified in
properties_list , Hibernate generates a value automatically. Automatic generation is available only if you use id generators. Otherwise, Hibernate will throw an exception during parsing. Database generators are
org.hibernate.id.SequenceGenerator and its subclasses, and objects that implement
org.hibernate.id.PostInsertIdentifierGenerator . The most notable exception is
org.hibernate.id.TableHiLoGenerator , which does not provide any way to get its values.
For properties that are projected as a version or timestamp, the insert statement gives you two options. You can either specify a property in
properties_list , in which case the value will be taken from the accompanying select expression, or removed from
properties_list , in which case the initial (seed) value defined in
org.hibernate.type.VersionType will be used.
Example 4.10. HQL INSERT expression Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ..."; int createdEntities = session.createQuery( hqlInsert ) .executeUpdate(); tx.commit(); session.close();