Use hibernate in Java SE

Source: Internet
Author: User
Tags java se
At present, it is easy to find that hibernate is quickly becoming a popular J2EE o/R ing tool and data integration framework (if not the most popular ). Hibernate provides clear and powerful tools for enterprise application developers to operate relational databases. However, what if you need to access entities encapsulated in J2EE Web applications externally? Is your development separate from the application, but the same entity is used to access your data? Or do you have to write additional web components to manage internal access to data?

In many cases, these problems may 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 method I used frequently before, that is, writing shell and SQL textbooks (or even stored procedures) to import data. However, because our data model is too complex, I decided to use the existing entities, spring Dao and services as much as possible outside the Web application and develop a custom j2se command line data loading tool.

Big question: What do you do?

Currently, many hibernate documents and examples are bound to containers. Containers are always used for both web applications and internal large-scale applications. People have a good reason to use it. Containers are designed to support various features, such as transaction processing, threads, and security. Nowadays, these features are all necessary tools for developing medium-sized and enterprise applications. But what do you do when you need to access entities outside the container? Do you use the existing architecture and code to solve the problem from a different perspective, for example, completely using another development language? Of course, we have no correct answer. In the rest of this article, I will illustrate my method: reuse existing entities/pojo outside the spring container.

At first, scripting languages such as Perl, Python, Ruby, and even TCL (Yes, I have done this before) seem to have many advantages. They can save a lot of time, get initial results easily, and avoid the potential complexity of hibernate. It is entirely possible that people can connect to the database with just a few lines of code. The query results have been printed and output to the terminal screen or log file. However, depending on your data model, things (always) become quite complex. For example, you have a table person with a foreign key belonging to the table address. When we add data, the table address does not insert data correctly, and the table person cannot be inserted. This is a typical transaction processing problem. Some people may say that this problem is not difficult to solve in the script language, just like in your main program. But the problem persists. Why? Isn't the business logic already in your application? Why should I write the code again? This is not the only case. You must repeat your work and business logic, which may lead to errors.

However, some people may think this is the best way, and they use the tools they find most suitable. Maybe you already have an independent architecture for reasons outside of the program; maybe you will load and test data in an independent database, then migrate the database to the product database after passing various tests. Maybe you outsource the database maintenance, and you just need to send the relevant documents to the Partners for them to handle those problems. In short, there will always be many reasons not to use the existing hibernate data layer. No one is right or wrong, but if you are willing to use the existing code out of your application, please refer to it. I will tell you some ways to solve your troubles.

Configuration

If you think you can use existing hibernate objects outside the container, you must manually manage all the configuration items, in the rest of this article, I use a Java program based on command line. Now that you have configured the hibernate xml configuration file, you should know the parameters to be provided, such as the JNDI datasource name, object ing file, and other attributes for processing SQL logs. If you want to use the command line program, you have to solve these problems in parsing the XML file and adding it to the configuration item. Although it is not difficult to parse XML files, this is not our focus. Therefore, we recommend that you use the propetries file. The properties file is intuitive and easy to load and read from. The following is the minimum attribute set required for hibernate configuration (excluding any entity ing ).

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=dbuser
hibernate.connection.password=dbpassword
hibernate.query.substitutions yes 'Y'

As you can see, the preceding attribute value specifies the database dialect, JDBC driver, Database URL, user name, user password, and whether to replace it with search. You only need to define the above values and save them in the file hibernate. properties (to put them in your class path), you can easily load them and fill them in 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 my 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);

In this way, we get the hibernate session class. However, we also need to solve the problem of how to use the existing entity ing. In hibernate in action, how to load objects from object ing XML files is described 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 describes the process of loading the message object definition from the hello package. This is a good example, but for applications with multiple entities, it is simple and error-prone. Not only is the ing relation hard-coded, but you have to manually manage to update the code loaded by the object each time you add a new object. In fact, there are simple ways to find and load ing relationships so that they are consistent with the latest jar files.

First, in your web server or enterprise server, the ing file must be placed in the class path so that hibernate can run normally. This is very good, because all you need to do is to use the same jar package and find the corresponding ing file name. Because you may have multiple jar files in your class path, you need to specify which jar package contains the ing file. The following is a method for finding ing relationships:

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 was not found in " +
        "classpath: " + cp);
    }
}

The above code mainly completes the following tasks: getting the classpath system attribute initialized by the Java Virtual Machine, finding the jar package containing the object ing file, and parsing the name of the ing file, then add it to an arraylist object. When our arraylist object is filled with the object ing name, it can be passed to the hibernate configuration object, as shown below:

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 ing relationship in the hibernate Session object, we can use the object.

Use session

For this, you can refer to the article or guide on Hibernate and persistence layer, or query various objects and instances to learn how to use transactions, so I am not going to elaborate on this. On the contrary, I will think more about what we need to do after using entities? How will this affect the hibernate Session object? Can I use existing business objects or even data access objects? When I set up the data layer, I used SPRING AND ITS classes to manage database connections, transactions, and sessions. These objects are defined in the XML configuration file and are closely integrated with many rules and relationships in spring. First, the DaO object will be introduced into the application service through spring dependency injection (for dependency injection, see Bruce Tate's five things I love about spring ). Then, configure the application service to catch Dao exceptions (through the xml configuration file) and let spring handle them. However, I think integrating spring into data loading applications will bring a lot of work. I made slight changes to Dao objects so that they can be used outside web applications.

For example, there is a method to save the person object in the persondao class. If the hibernate session is created by the container, this method cannot be used outside the container, because this requires a configured session object. The following is a typical persondao, which is supported by the spring container for session.

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 to use hibernate. Besides, because the hibernatetemplate class maintains most common operations, you only need to focus on specific persistent layer requirements. Of course there should also be corresponding exception handling, but in this example, as long as the above is enough.
Now, to add session support outside the container, we only need to make some 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 create sessionfactory from any session object. This is a highly flexible design by the spring team, making it easier to reuse existing code.
Maybe you didn't use spring, but used a completely different method. If you do not like spring injection, you can also use JNDI to find the session object:

Listing 8:

import net.sf.hibernate.Session;

public class PersonDAO {

// This example assumes that 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 simplest method to use outside the container is to add a constructor with session parameters, as shown below:

Listing 9:

import net.sf.hibernate.Session;

public class PersonDAO {

// This example assumes that 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 have not handled too many exceptions and transaction problems. Even if we share a session object in multiple methods, this will lead to some concurrent transaction problems (depending on how the container or framework processes the object instance ). However, I think the above example shows how to reuse a large number of existing data layer code. You only need a little creative idea. To find out whether you want to use the existing entities and Dao outside the application server, continue to try again.

Conclusion

As you can see, using hibernate entities and Dao outside the Web Container requires skill, but this can certainly be done. The biggest difficulty lies in how to find the ing between entities and how to reset (or modify) existing data access objects (DAO ). When processing the latter, be careful when dealing with transaction issues, because no application service can be relied on. However, we can still access all objects and objects for persistence, which saves a lot of time to re-develop code. 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.