Object Relational Mappings: Object-relational Mapper (O/RM)
We want to read and write objects directly in relational databases without having to manipulate SQL in code, which requires Object-relational Mapper.
We may have dozens of tables, each table has a lot of columns, so the entire deletion of the code is very cumbersome, the use of O/RM, our code can be greatly simplified. Examples of students who use the previous study are still as follows:
Public Product getstudent (long id) {return
this.getcurrenttransaction (). Get (Student.class, id);
public void Addstudent (Student Student) {
this.getcurrenttransaction (). persist (Student);
}
public void Updatestudent (Student Student) {
this.getcurrenttransaction (). Update (Student);
public void Deletestudent (Student Student) {
this.getcurrenttransaction (). Delete (Student);
We need to tell O/RM mapping rules, different o/rm have different mapping methods, there is the cost of migration. A high abstraction hides the details of the implementation, and sometimes a reasonable statement (SQL) is critical to performance, and we can analyze it through the statement log of the database service. Many o/rm can automatically generate table schema (automatically generate tables) based on mapping instructions, but we should not do so, especially in production environments or products, remember that we should design our own tables. If the table design is poor, it is your fault, not o/rm. Java Persistence API
There are a number of O/RM products, such as top Link and its later Eclipse Link,ibatis, and later Mybatis,hibernate Orm and nhibernate for. Net. To address the cost of different o/rm migrations, a Java persistence API emerged and was added as JSR 220 in Java EE 5. In 2009, JPA 2.0 joined the Java EE 6 as JSR 317, and in 2013, JPA2.1 as JSR 338 to join Jaav EE 7.
JPA uses JDBC to execute SQL statement, but the encapsulation is good, we don't use the JDBC API directly, and we avoid using SQL statements directly. Hibernate ORM
Hibernate is the implementation of JPA. In Maven, scope is set to runtime, that is, not using its APIs directly, but using JPA. However, Hibernate provides some of the capabilities outside of JPA and should be set to compile if it is to be used. These additional features are highlighted below, and these features are only preliminary and will not be covered later in the study. using hibernate mapping Files
Earlier versions of Hibernate used XML files to describe the mappings, supported annotation in version 3.5, including JPA tags. You can now use XML to map, but you should only use hibernate rather than JPA scenarios.
Generally, the XML mapping file is placed in resource, with the same name as the corresponding entity, and the path is the same, for example, a com.example.entities.Product class corresponds to Product.hbm.xml, the COM under resource /example/entities/product.hbm.xml. Examples are as follows:
<?xml version= "1.0" encoding= "UTF-8"?> <! DOCTYPE hibernate-mapping Public "-//hibernate/hibernate mapping DTD 3.0//en" "http://www.hibernate.org/dtd/ Hibernate-mapping-3.0.dtd "> "Read" obtains entity return (PRODUCT) Session.get (Product.class, id) via surrogate key; Insert adds entity and returns the generated ID.
If an ID already exists, this ID is updated.
Session.save (product); /* "Insert" is also to increase entity, and more secure. When a transaction is closed, persist () does not perform an insert (SQL) operation, and Save () opens an extra transaction. Save () can immediately get the ID, and persist () does not guarantee that execution, to be followed by flush () is guaranteed to execute immediately, so it does not return the automatically generated ID. We can add flush () in the back to get. Flush () will cause the current pending statement to execute immediately, but will not close the session. Flush () is also associated with the statement queue of Hibernate, where there are multiple actions within a transaction, but the actions are not necessarily the order we think they are. At flush time, the order of execution since the last flush () is: * 1, entity insert operation in sequence * 2, sequential entity update operation * 3, sequential collection Delete operation * 4, Sequential collecti Insert,update and delete operations on element * 5, insert operation in order Collection * 6, press rinse the new entity delete operation * through Flush () we can ensure that we expect the order, Note that save () is executed immediately, regardless of flush ().
We use flush () to be very careful and may cause confusion/session.persist (product);
Session.flush ();
The use of the "Update" Udpate () is somewhat special, does not allow the session, before the entity have operations, that is, not before the get,save,persist, or throw an exception session.update (product);
The "Update" merge does not have operational restrictions on entity before the session, so it is a more common way to session.merge (product);
"Delete" session.delete (product); //"Evict" Expulsion: expulsion or separation from the session entity, but no actual impact on the database. If there is a statement that has not been executed at this time, it will be canceled and will not be executed entity.
If we need to expel all the entity, use Clear () session.envict (product); Session.clear ();
Use surrogate key to query of course is not the only direction, the table can have other key, not all through primary key. You can use the Org.hibernate.Criteria API or the Org.hibernate.Query API, which is equivalent to the following
Return (Product) Session.createcriteria (Product.class)
. Add (Restrictions.eq ("SKU", SKU))
. Uniqueresult ();
The statements inside are HQL, similar to SQL, but with the concept of objects, not tables, columns. return
(product) session.createquery (' from Product p WHERE p.sku =: SKU ')
. SetString ("SKU", SKU)
. Uniqueresult ();
Here is an example of returning the prefix of the first name to Java, a year ago:
Return (list<product>) Session.createcriteria (Product.class)
. Add (restrictions.gt ("dateposted", Instant.now (). Minus (365L, chronounit.days)))
. Add (Restrictions.ilike ("name", "Java", Matchmode.start))
. AddOrder ()
. List ();
Return (list<product>) session.createquery ("from Product p WHERE dateposted >: Oneyearago and Name Ilike:namelik E ORDER by name ")
. Setparameter (" Oneyearago ", Instant.now (). Minus (365L, chronounit.days)).
SetString (" Namelike "," java% ")
. List ();
sessionfactoryThe session needs to be attached to the JDBC connection, Sessionfactory provides the relevant actions for session acquisition:
Open a new session, using the default configuration (datasource,interceptors, etc.) session session
= Sessionfactory.opensession ();
Opens a new session with the specified setting session session
= Sessionfactory.withoptions ()
. Connection (Connection). Opensession () ;
Open a new session, block all SQL statements, and make changes, such as setting the Schema= "@SCHEMA @" session Session
= Sessionfactory.withoptions ()
. Interceptor (New Emptyinterceptor () {
@Override public
string onpreparestatement (String sql) {
return Sql.replace ("@SCHEMA @", SCHEMA);
}
). Opensession ();
Hibernate ORM can have stateless session, especially suitable for a large number of data operations, my understanding is non-transactional. To open a stateless session, you can turn on the default amount of stateless sessions by using the. openstatelesssession () or through. Withstatelessoptions () to open a custom stateless conversation. Stateless sessions are not supported for the current session.
Sessionfactory is a thread-safe that will return the session that was previously opened in the current thread. Session Session
= Sessionfactory.getcurrentsession ();
creating a sessionfactory Bean in the spring framework
The Spring framework provides sessionfactory to manage the creation and shutdown of sessions well, avoiding memory leaks from resource access.
FOR XML methods, Defines the Org.springframework.orm.hibernate5.LocalSessionFactoryBean, returns Sessionfactory.localsessionfactorybean, and implements Org.springfram The Ework.dao.support.PersistenceExceptionTranslator interface, which converts an ORM exception for hibernate into a common persistent exception for the spring framework.
The XML configuration is as follows [2]:
<bean id= "Sessionfactory" class= "Org.springframework.orm.hibernate5.LocalSessionFactoryBean" > <property Name= "DataSource" ref= "DataSource"/> <property name= "annotatedclasses" ref= "hibernateclasses"/> <pro
Perty name= "Hibernateproperties" > <props> <prop key= "Hibernate.dialect" > ${hibernate.dialect} </prop> <prop key= "Hibernate.show_sql" > ${hiber
Nate.show_sql} </prop> <prop key= "Hibernate.format_sql" >true</prop> <prop key= "Hibernate.generate_statistics" > ${hibernate.generate_statistics} </prop>
; <prop key= "Hibernate.hbm2ddl.auto" > ${hibernate.hbm2ddl.auto} </prop> < /props> </property> </bean> <bean id= "TransactionManager" class= "Org.springframework.orm.hibern" Ate5. HibernatetRansactionmanager "> <property name=" sessionfactory "ref=" Sessionfactory "/> </bean>
The Java code is configured as follows, configured in the root context
@EnableTransactionManagement public
class Rootcontextconfiguration implements Asyncconfigurer, schedulingconfigurer{...
@Bean public
persistenceexceptiontranslator Persistenceexceptiontranslator () {return
new Hibernateexceptiontranslator ();
}
@Bean public
Hibernatetransactionmanager TransactionManager () {
Hibernatetransactionmanager manager = new Hibernatetransactionmanager ();
Manager.setsessionfactory (This.sessionfactory ());
return manager;
}
@Bean public
sessionfactory sessionfactory () {
Localsessionfactorybuilder builder = new Localsessionfactorybuilder (This.datasource ());
Builder.scanpackages ("Com.wrox.entities");
Builder.setproperty ("Hibernate.default_schema", "dbo");
Builder.setproperty ("Hibernate.dialect", MySQL5InnoDBDialect.class.getCanonicalName ());
return Builder.buildsessionfactory ();
}
RELATED links: My professional Java for WEB applications related articles