Site Sponsors:
Hibernate: Flush -v- Commit 
Once again, the question has been asked - Must we only use transactions with Hibernate?

The answer is no!

Indeed, assuming we have run something like the following:

drop table "NAGY".ACCOUNTS;
create table "NAGY".ACCOUNTS
(
ACCOUNT_ID BIGINT not null primary key,
LEGALNAME VARCHAR(255)
);


After we reverse engineer, then we can "go .flush():"

        Date date = new Date();
long ZID = date.getTime();
SessionFactory fact = NewHibernateUtil.getSessionFactory();
Session session = fact.openSession();

// Create
Accounts ref = new Accounts();
ref.setAccountId(ZID);
ref.setLegalname("NAGY");
session.save(ref);
session.flush();
session.clear();

// Read Created
ref = (Accounts) session.load(Accounts.class, ZID);
System.out.println("Got: " + ref.getLegalname());

// Update
ref.setLegalname("Professor Nagy");
session.update(ref);
session.flush();

// Read Update
ref = (Accounts) session.load(Accounts.class, ZID);
System.out.println("Got: " + ref.getLegalname());

// Delete
ref = (Accounts) session.load(Accounts.class, ZID);
session.delete(ref);
session.flush();

session.close();


... or we can "go .commit()":

        // Create
Accounts ref = new Accounts();
ref.setAccountId(ZID);
ref.setLegalname("NAGY");
Transaction trans = session.beginTransaction();
session.save(ref);
trans.commit();
session.clear();


... We can even do a bit of both!

        Date date = new Date();
long ZID = date.getTime();
SessionFactory fact = NewHibernateUtil.getSessionFactory();
Session session = fact.openSession();

// Create - a 'la Transaction
Accounts ref = new Accounts();
ref.setAccountId(ZID);
ref.setLegalname("NAGY");
Transaction trans = session.beginTransaction();
session.save(ref);
trans.commit();
session.clear();

// Read Created
ref = (Accounts) session.load(Accounts.class, ZID);
System.out.println("Got: " + ref.getLegalname());

// Update
ref.setLegalname("Professor Nagy");
session.update(ref);
session.flush();

// Read Update
ref = (Accounts) session.load(Accounts.class, ZID);
System.out.println("Got: " + ref.getLegalname());

// Delete - a la Transaction
trans = session.beginTransaction();
ref = (Accounts) session.load(Accounts.class, ZID);
session.delete(ref);
trans.commit();

session.close();

Indeed, the standard says lots of things things like "The entity X will be entered into the database at or before transaction commit or as a result of the flush operation."

--Enjoy,

-Rn


[ add comment ] ( 1876 views )   |  permalink  |  related link
MyEclipse: 123 Hibernate! 
Anyone who has been hanging around .Net for a while knows that the Framework has a tendency to "borrow" ideas from anywhere ... and everywhere!

Indeed, far from being original, the sad truth in our day is that achievement in most industries today is far more about imitation, than innovation!

MyEclipse


So whilst I was recently 'rocking at the BS of A using Entity Frameworks (why do you think we call it a 'gig'?), my thoughts turned to revisiting that spark on innovation that - for me - started it all: Hibernate.

Of course, all things have their time to incubate. Indeed, happy as I have been to teach a 13-week boot camp in Chicago recently, I was even more happy to hear that a student was using the "reverse engineering" capability of MyEclipse Blue (aka "MEB") (For those who don't know about, MEB is all about using Java on IBM - or "Big Blue". --The color choice has absolutely nothing to do with playing the 'Sax across the smokey bars along Chicago's West Side...)


Big Blue


Intent upon reaping multi-thousand-dollar savings, most folks have been replacing IBM's Rational Application Developer Studio (IBM RAD,) with MEB. -Far from being a completely new tool set, MEB builds on MyEclipse - a set of enhancements to Eclipse. Familiar tools == familiar productivity.

Hibernate Tooling


Those who feel comfortable with the way Hibernate works (XML, Sessions, Annotations, and Transactions) should feel free to play with the reverse-engineering capabilities of MyEclipse. -While seldom recommended for the first-timer (Why? Because IMHO mastery dictates that everyone needs to put in that "sweat equity": Bottom-up experience helps us debug / troubleshoot sessions via JDBC, SQL, HQL, and more,) the ability to quickly view, create, & review Database Objects is a nice place to BEGIN many a database project. (i.e. Better learn how to walk, before we run?)

MyEclipse Hibernate Wizard


Evolving as it did from Spring and XML, modern Hibernate is now mostly about @Annotations. Yet, in order to use Annotations, we need to be using Java Version 1.5, or greater.

Step 1: Prep Your Project


After we have created both a project and a package to put the generated Java code into, there are three easy steps to adding Hibernate to our undertakings:


Project-Folder Right-Click Example


Because all of these features are also under the MyEclipse Menu Item, no matter if we are right clicking on the project folder, or selecting the features from the main menu-bar, be SURE to BOTH (1) "Add Hibernate Capabilities" and to (2) "Enable Hibernate Annotations Support". Failure to Enable Hibernate Annotations Support will tell Reverse Engineering to generate the wrong kind of session factory.


Enable Hibernate Annotations


Step 2: Reverse Engineer Your Tables


Once properly option-laden, the NEXT most important thing to do is to (3) connect to your database.

Note that the Hibernate Reverse engineering Option is part of the "MyEclipse Database Explorer Prospective", so keep that database prospective open.

After the database connection has been established, the next right-click menu-selection should take place after we have selected the database table(s) we want to generate Java for. --Once your (4) table(s) have been selected, all that remains is to right-click on the set to (5) select the "Hibernate Reverse Engineering" Wizard.


Database Table(s) - Right-Click View


NOTE: From That Hibernate Reverse Engineering Dialog - No matter which options selected, be sure to select the "Enable Hibernate Annotations Support" -Feature.


Reverse-Engineering -w- Annotations


Migrating away from XML object-mappings, to favor Hibernate's 1.5+ Annotations, is what this article is all about!

Step 3: Use Your Objects


So here we are - all Data Access Objects (DAO) / data table classes have been generated, and the XML is fine. All that remains is to (6) use those generated objects!

Of course, as Shakespeare said, therin lies the rub ...

For me, using any new set of Hibernate Objects in production is most sanely accomplished after we have tackled some test cases.

In my case, a simple Create, Read (1:1), Update, and Delete (CRUD) exercise for one of the tables is usually in order:

public static void main(String[] args) {
Session session = HibernateSessionFactory.getSessionFactory()
.openSession();
Transaction trans = null;
try {
trans = session.beginTransaction();
UserInfo ref = new UserInfo(12346L, "MageFoo");
ref.setPurchase(0.45D);
session.save(ref);
trans.commit();
session.clear();

trans = session.beginTransaction();
session.load(ref, 12346L);
ref.setPurchase(123.45D);
session.update(ref);
session.delete(ref);
trans.commit();
} catch (Exception ex1) {
trans.rollback();
System.err.println(ex1);
} finally {
session.close(); // matches openSession(above)
}

}
... where UserInfo is a table for which Java has been generated.

Note how easy Hibernate makes the entire CRUD operation. The hand-coding of SQL Statements, as well as Spring-XML Object Mappings, is no longer required!

Business Objects


Last but not least, new users should note that Hibernate DAOs make use of tons of proxy objects.

While proxies make memory storage incredibly efficient, using proxies also make us want to create some type of (7) BUSINESS Objects (BO), too. -Why? Because Hibernate's proxies loose their meanings once outside of a database session.

(Since of Hibernate 3 (JPA Release), lazy loading is the default. -Yes, the use of proxies can indeed be changed ... but doing THAT is another story!)

While we can always .merge() Detached objects into another session, putting data into BOs makes DAO-payloads available elsewhere. Indeed, the need to transfer DAO Data into surrogate objects is so frequent, that, when lacking any other business-justification, we often refer to the classes as "Data Transfer Objects" (DTOs).

Conclusion


We hope that this spark off of MyEclipse will inspire you to use Hibernate Annotations. As an avid NetBeans and JBuilder user as well, allow me to note - once generated by MyEclipse - that we can add our generated DAOs, as well as Hibernate, to any Java project.

Some notes:

NOTE: Maintenance


Classes created by the above Wizard(s) will bear the following signature:
@author MyEclipse Persistence Tools

If we are using NetBeans, we will see:
/**
* Products generated by hbm2java
*/

Unless we *WANT* things to be over-written, then beware of the casual code-re-generation.

NOTE: Log4J


At the time of this writing, Hibernate relies upon Log4J. If your project is complaining about missing the same, then create a log4j.properties file:
# Set root logger level to ERROR and add an appender called A1.
log4j.rootLogger=ERROR, A1
# set A1 to be the console
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# Use the PatternLayout for A1
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-5p %c - %m%n

Next, those INFO message, as see at start-up on the console, can be also annoying. To turn them off, simply add:
log4j.logger.org.hibernate=warn
to that log4j.properties file.

-Be sure to put the properties file directly under /src... right next to that Hibernate configuration file.

NOTE: GetCurrentSession


For the sake of the training I teach, all would be amiss if we did not add that using a:


Session session = HibernateSessionFactory.getSessionFactory()
.getCurrentSession();
Requires that we have MANUALLY ADDED a:

<!-- The place to store the current session -->
<property name="current_session_context_class">
org.hibernate.context.ThreadLocalSessionContext
</property>

-to the <session-factory> Section of the hibernate.cfg.xml file.

Last, but not least, please remember: DO NOT CLOSE A CACHED SESSION -That next transaction will surely have problems ... ?!

NOTE: Other Options


From the above example, the astute reader will infer that Hibernate is doing allot of things for us.

While annotations have simplified things, there are many things to tweak in the hibernate.cfg.xml.

Indeed, from both the run-time, as well as XML, options include:
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>
These particular options belong to <hibernate-configuration>
<session-factory>
... -Their names are pretty much self-explanatory. Feel free to 'google them, as inspired.

NOTE: What About NetBeans?


I love NetBeans - for those of you who share the love, here is yet another tutorial.


[ add comment ] ( 2567 views )   |  permalink  |  related link
XML IO Using Generics - Before Java 1.7 
In as much as we often teach students who are using an older version of Java, we decided to put together another demonstration. -An example that can readily be targeted for earlier versions of Java.

Remember - the use of Java Serialization is NOT required. In order to use the XML serialization technique, all we need is a POJO!

First, the I/O Demonstration (note that checking for nulls (etc) has been omitted so as to enhance conceptual review):

package com.soft9000.file;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class XmlClassIO<T> {
public String sLastError = "";

public boolean write(String fileName, T ref) {
try {
XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(
new FileOutputStream(fileName)));
encoder.writeObject(ref);
encoder.close();
return true;
} catch (Exception ex) {
this.sLastError = ex.getMessage();
return false;
}
}

public T read(String fileName) {
try {
XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(
new FileInputStream(fileName)));
T result = (T) decoder.readObject();
decoder.close();
return result;
} catch (Exception ex) {
this.sLastError = ex.getMessage();
return null;
}
}
}

Next, the testable class:

package com.soft9000.file;

import java.util.List;
import java.util.ArrayList;

public class BigBadFoo {

private ArrayList<String> list = new ArrayList<String>();
private String foo;

public BigBadFoo() {

}

public void setList(List<String> someList) {
this.list = new ArrayList<String>(someList);
}

public List<String> getList() {
return this.list;
}

public void setFoo(String string) {
this.foo = string;
}

public String getFoo() {
return this.foo;
}

public boolean equals(Object obj) {
if (obj instanceof BigBadFoo) {
if (super.equals(obj))
return true;
BigBadFoo ref = (BigBadFoo) obj;
if (foo.equals(ref.foo) == true) {
return list.equals(ref.list);
}
}
return false;
}

}

Finally, the test case:

package com.soft9000.file;

import java.util.ArrayList;

/**
* Proof of concept.
*
* @author Profnagy
*
*/
public class Main {

public static void main(String[] args) {
ArrayList<String> SomeList = new ArrayList();
SomeList.add("one");
SomeList.add("two");
SomeList.add("three");
BigBadFoo foo1 = new BigBadFoo();
foo1.setFoo("12345");
foo1.setList(SomeList);
com.soft9000.file.XmlClassIO<BigBadFoo> io = new XmlClassIO<BigBadFoo>();
io.write("test.xml", foo1);

BigBadFoo foo2 = io.read("test.xml");
if(foo2.equals(foo1) == false) {
System.out.println("Serialization Failure.");
System.exit(-1);
}
System.out.println("Serialization Success.");
}
}

Notes


The above has been designed to be cut-and-pasted.

Be sure to re-format the code after doing so.


Enjoy,

-Rn

Student Note: Regression


While fine for illustrative purposes, over time things can change.

In as much as we might want to be sure that things actually break when they should, it is always nice to add-in a few "should break" tests, as well. Such will help us a-lot as we perform feature regression tests, over time:

Here is a simple example:
      
foo2.setFoo("shazam");
if(foo2.equals(foo1) == true) {
System.out.println("Assignment/Equality Regression.");
System.exit(-1);
}


[ add comment ] ( 2008 views )   |  permalink  |  related link

<<First <Back | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Next> Last>>