Using the hibernate framework in Java SE

Source: Internet
Author: User
Tags object exception handling sql net postgresql query access tomcat
It is now easy to find that hibernate is rapidly becoming the popular Java/O mapping tool and Data Integration Framework (if not the most popular). Hibernate provides a clear and powerful tool for enterprise application developers to operate relational databases. But what if you need to be outside to access the entities packaged in the Java EE Web application? Is your development a separate, yet identical entity for the application to access your data? Or do you have to write additional Web Components to manage internal access to the data?

In many cases, these problems can occur. My situation is that my company needs to import records from multiple vendors with multiple file formats into the database. I think of the methods I used to use, which is to write shell and SQL textbooks (even stored procedures) to import data. But because our data model is too complex, I decided to make the most of the existing entities, Spring DAO, and services outside of the Web application and develop a custom J2SE command-line data loading tool.

   big question: What should you do?

Many hibernate documents and examples are now bound to the container. Whether it is a Web application or a large internal application, the container is always used. People have good reason to use it. Containers are designed to provide support for a variety of features, such as transaction processing, threading, and security. Today, these features are the tools necessary to develop midsize and enterprise applications. But what happens when you need to access entities outside the container? Do you use the existing architecture and code, or do you solve the problem from a different perspective, such as completely using another development language? Of course, we don't have the right answer. In the remainder of this article, I'll explain my approach: reusing existing entity/pojo outside of the spring container.

At first, scripting languages such as Perl,python,ruby and even Tcl (yes, I've done this before) seem to have a lot of advantages. They can save a lot of time, get the initial results easily, and avoid the potential complexity of many hibernate. It is possible for people to connect to a database with just a few lines of code, and the query results are printed out to the terminal screen or log file. However, depending on your data model, things can become quite complex. For example, you have a table person, which has a foreign key that belongs to the table address. When we add data, the table address does not insert data correctly, which causes the table person to not be inserted. This is a very typical issue of transaction processing. Some might say that the problem is not difficult to solve in scripting languages, as in your main program. But the problem still exists, why do you do it? Isn't the business logic already in your application? Why are you writing the code again? And it's not the only case where you have to repeat your work and business logic, which can lead to mistakes.

However, some people feel that they can do it, and they use the tools they find most appropriate. Maybe you already have some kind of independent structure for reasons outside the program; perhaps you will download and test data in a separate database, then migrate it to the product database after testing it, or maybe you outsource the database maintenance, and you just need to send the relevant documents to the partners to deal with those issues. In short, there are always many reasons not to use the existing Hibernate data layer. No one is right or wrong, but if you can and will be willing to use the existing code outside of your application, look down. I'll tell you a few ways that can solve a lot of your problems.

   Configuration

If you think you can use an existing Hibernate object outside of the container, the first thing you need to do is to manually manage all of your configuration items, and I'm using a command-line based Java program for the remainder of this article. Now that you have configured the hibernate XML configuration file, you should know the parameters you need to provide, such as the Jndi datasource name, the entity mapping file, and other properties that handle the SQL log. If you want to use a command-line program, you'll have to solve the problem of how to parse the XML file and add it to the configuration item. Although parsing XML files is not difficult, it is not in itself our focus. Therefore, I recommend using the Propetries file, the properties file is more intuitive and easy to load and read data from. The following is the minimum set of attributes required to configure Hibernate (excluding any entity mappings).

Listing 1:

Hibernate.dialect=net.sf.hibernate.dialect.postgresqldialect
Hibernate.connection.driver_class=org.postgresql.driver
Hibernate.connection.url=jdbc:postgresql://devserver/devdb
Hibernate.connection.username=dbuserhibernate.connection.password=dbpassword
hibernate.query.substitutions yes ' Y '
As you can see, the attribute values above specify the database dialect, JDBC driver, database URL, username, user password, and whether to use find substitution. As long as you define the above values and save them in the file hibernate.properties (to be placed in your classpath), you can easily load and populate the Hibernate configuation class.

Listing 2:

Properties Props = new properties ();
try {
Props.load (Props.getclass (). getResourceAsStream ("hibernate.properties"));
}catch (Exception e) {
System.out.println ("Error Loading Hibernate properties.");
E.printstacktrace ();
System.exit (0);
}
String Driver = Props.getproperty ("Hibernate.connection.driver_class");
String Connurl = Props.getproperty ("Hibernate.connection.url");
String username = props.getproperty ("Hibernate.connection.username");
String Password = props.getproperty ("Hibernate.connection.password");
In me examples, I use Postgres, but Hibernate
Supports virtually every popular DBMS out
There. Class.forName ("Org.postgresql.Driver");
Connection conn = drivermanager.getconnection (connurl, username, password);
Configuration cfg = new Configuration ();
Cfg.setproperties (props);
Sessionfactory sessions = Cfg.buildsessionfactory ();
Session session = Sessions.opensession (conn);
So we get the Hibernate session class. But we also need to solve the problem of how to use existing entity mappings. In the book Hibernate in action, mention is made of how to load from the entity mapping XML file, as follows:

Listing 3:

Configuration cfg = new Configuration ();
Cfg.addresource ("Hello/message.hbm.xml");
Cfg.setproperties (System.getproperties ());
Sessionfactory sessions = Cfg.buildsessionfactory ();
This code clearly illustrates the process of adding a message entity definition from the Hello package. Good for this example, but for applications that have multiple entities, it's simple and error-prone. Not only is the mapping relationship hard coded, but it also requires manual management to update the entity-loaded code each time a new entity is added. There is a simple way to find and load a mapping relationship to keep it consistent with the latest jar files.

First of all, in your Web server or enterprise server, the mapping file needs to be placed in the classpath so that hibernate can run normally. This is good because all you have to do is use the same jar package and find the name of the corresponding mapping file. Because you may have multiple jar files in your classpath, you need to specify which jar package contains the mapping file. Here's a way to find a mapping relationship

Listing 4:

String CP = System.getproperty ("Java.class.path");
String jarfile = null;
List hbmlist = null; string[] Cparr = Cp.split ("\:");
for (int j=0;j<cparr.length;j++) {
The following assumes our entities
are wrapped up in a jar file
Called ' Dbobjs.jar '
if (Cparr[j].indexof ("Dbobjs.jar")!=-1)
Jarfile= (Cparr[j]);
}
if (jarfile!= null) {
Jarfile jar = new Jarfile (new File (Jarfile));
Enumeration E = Jar.entries ();
if (E.hasmoreelements ())
{
Hbmlist = new ArrayList ();
while (E.hasmoreelements ()) {
Object comes back as Jarfile$jarfileentry
Jarentry entry = (jarentry) e.nextelement ();
if (Entry.getname (). IndexOf (". Hbm.xml")!=-1)
{
Hbmlist.add (Entry.getname ());
}
}
}else {
System.out.println ("error:the entity jar Dbobjs.jar is not found in" + "Classpath:" + CP);
}
}
The code above mainly accomplishes the following things: Get the Classpath System properties initialized by the Java Virtual machine, find the jar package containing the entity mapping file, resolve the name of the mapping file, and add it to a ArrayList object. When our ArrayList object is filled with the name of the entity map, it can be passed to the Hibernate Configuration object as follows:

Listing 5:

Configuration cfg = new Configuration ();
Iterator iterator = Hbmfilenames.iterator ();
while (Iterator.hasnext ()) {
Cfg.addresource ((String) Iterator.next ());
}


As long as we configure the correct mapping relationship in the Hibernate session object, we can use the entity.

   Use session

In this context, you can refer to articles or guides about hibernate and persistence layers, and you can query various objects and instances to understand how to use the transaction, so I'm not going to say that in detail. Instead, I will think more about using the entity what do we need to do? How does this affect the Hibernate session object? Can I use an existing business object, or even a data access object? When I set up the data tier, I used spring and some of the classes it provided to manage database connections, transactions, and sessions. These objects are defined in the XML configuration file and are tightly integrated with many rules and relationships in spring. First, with Spring's dependency injection, DAO objects are introduced into the application service (for dependency injection, see Bruce Tate's "Five Things I Love about Spring"). Then, configure the application service to catch the DAO exception (through the XML configuration file) and let spring handle it. But because I think integrating spring into a data-loading application can be quite a lot of work. I made minor changes to the DAO objects so that they can be used outside of the Web application.

For example, there is a method for saving a person object in the Persondao class. If the hibernate session is built by a container, this method cannot be used outside the container because it requires a configured session object. The following is a typical Persondao, which provides support for the session by the Spring container.

Listing 6:

Import Org.springframework.orm.hibernate.HibernateTemplate;
Import Test.pojos.Person;
public class Persondao extends Hibernatetemplate
{
Public Persondao () {} Public person save (person Aperson)
{
if (Aperson!= null)
Super.save (person);
return person;
}
}
The above class inherits the spring Hibernatetemplate class, which provides a variety of good base class methods for using Hibernate. And since the Hibernatetemplate class maintains most of the common operations, you only need to focus on specific persistence layer requirements. Of course, there should be corresponding exception handling, but in this example, as long as the above is enough.
Now, to support the session in the container Plus, we just need to make a few minor changes:

Listing 7:

Import Org.springframework.orm.hibernate.HibernateTemplate;
Import net.sf.hibernate.Session;
Import Test.pojos.Person;
public class Persondao extends Hibernatetemplate
{
Public Persondao () {}
public void Setexternalsessionfactory (session asession) {
Setsessionfactory (Session.getsessionfactory ());
}
Public person Save (person Aperson) {
if (Aperson!= null)
Super.save (person);
return person;
}
}
Because the Hibernatetemplate class inherits from the Hibernateaccessor class, we can build Sessionfactory from any session object. This is a highly flexible design for the spring team, making it easier to reuse existing code.

Maybe you're not using spring but using a completely different approach. If you don't like spring's injection, you can also find the session object through Jndi:

Listing 8:

Import Net.sf.hibernate.session;public class Persondao {
This example assumes so there is a Hibernate
Session object at the following JNDI location
On a Tomcat 5.5 server:
Java:/comp/env/obj/hibernatesession
Private session session;
Public Persondao () {
try {
Context Initctx = new InitialContext ();
Context Envctx = (context) initctx.lookup ("java:comp/env");
Session = (session) envctx.lookup ("Obj/hibernatesession");
}catch (Exception e) {
E.printstacktrace ();
}
}
Public person Save (person Aperson) {
if (Aperson!= null) session.save (person);
return person;
}
}
The above example relies on the application server to make the Hibernate session object available. The easiest way to use outside the container is to add a constructor with the session parameter, as follows:

Listing 9:

Import net.sf.hibernate.Session;
public class Persondao
{
This example assumes so there is a Hibernate
Session object at the following JNDI location
On a Tomcat 5.5 server:
Java:/comp/env/obj/hibernatesession
Private session session;
Public Persondao () {
try {
Context Initctx = new InitialContext ();
Context Envctx = (context) initctx.lookup ("java:comp/env");
Session = (session) Envctx. Lookup ("Obj/hibernatesession");
}catch (Exception e) {
E.printstacktrace ();
}
}
Public Persondao (Session asession) {
session = Asession;
}
Public person Save (person Aperson) {
if (Aperson!= null) session.save (person);
return person;
}
}
Of course we do not deal with too many anomalies, problems of affairs. Even if we share a session object within multiple methods, this can cause some concurrent transaction problems (depending on how the container or framework handles the object instance). But I think it's obvious that the above example demonstrates how to reuse a large number of existing data-layer code. Just need a little creative idea. To figure out if you want to use existing entities and DAO outside of the application server, try again.

   Conclusions

As you can see, it's tricky to use Hibernate entities and DAO outside of a Web container, but that's certainly possible. The biggest difficulty is finding an entity mapping relationship and how to reset (or modify) an existing data Access object (or DAO). When dealing with the latter, be careful with transaction issues, because no application services can be relied upon. In the end, however, we have access to all entities and persistent objects, which saves a lot of time in the development of code. Wish you good luck!!



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.