NetBeans, JSF, and MySQL Primary Keys using AUTO_INCREMENT

I recently had the opportunity to spin up a small web application using JSF and MySQL. Having developed JSF apps with Oracle Database back-ends before and possessing some small familiarity with MySQL (sans JSF), I thought this would be a cakewalk. Things did go pretty smoothly...but there was one little "gotcha" that took more time than the few seconds it really warranted.


The Problem

Every DBMS has its own way of automatically generating primary keys, and each has its pros and cons. For the Oracle Database, you use a sequence and point your Java classes to it using annotations that look something like this:


@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="POC_ID_SEQ")

@SequenceGenerator(name="POC_ID_SEQ", sequenceName="POC_ID_SEQ", allocationSize=1)


Between creating the actual sequence in the database and making sure you have your annotations right (watch those typos!), it seems a bit cumbersome. But it typically "just works", without fuss.


Enter MySQL. Designating an integer-based field as PRIMARY KEY and using the keyword AUTO_INCREMENT makes the same task seem much simpler. And it is, mostly. But while NetBeans cranks out a superb "first cut" for a basic JSF CRUD app, there are a couple of small things you'll need to bring to the mix in order to be able to actually (C)reate records. The (RUD) performs fine out of the gate.


The Solution

Omitting all design considerations and activity (!), here is the basic sequence of events I followed to create, then resolve, the JSF/MySQL "Primary Key Perfect Storm":

  1. Fire up NetBeans.
  2. Create JSF project.
  3. Create Entity Classes from Database.
  4. Create JSF Pages from Entity Classes.
  5. Test run. Try to create record and hit error.

It's a simple fix, but one that was fun to find in its completeness. :-) Even though you've told it what to do for a primary key, a MySQL table requires a gentle nudge to actually generate that new key value. Two things are needed to make the magic happen.


First, you need to ensure the following annotation is in place in your Java entity classes:


@GeneratedValue(strategy = GenerationType.IDENTITY)


All well and good, but the real key is this: in your controller class(es), you'll have a create() function that looks something like this, minus the comment line and the setId() call in bold red type:


    public String create() {

        try {

            // Assign 0 to ID for MySQL to properly auto_increment the primary key.

            current.setId(0);

            getFacade().create(current);

            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("CategoryCreated"));

            return prepareCreate();

        } catch (Exception e) {

            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));

            return null;

        }

    }


Setting the current object's primary key attribute to zero (0) prior to saving it tells MySQL to get the next available value and assign it to that record's key field. Short and simpleā€¦but not inherently obvious if you've never used that particular combination of NetBeans/JSF/MySQL before. Hope this helps!


All the best,

Mark



Comments:

very helpful... luckily I found this soon after searching! Real life saver!

Posted by jason on July 01, 2012 at 11:44 PM PDT #

What do you mean by "Controller classes"? the search facades? i cannot find this create method anywhere, im using netbeans 7.3.1. -Thanks

Posted by Neil Hall on January 22, 2014 at 10:47 PM PST #

Hi Neil,

When you let NetBeans create "JSF Pages from Entity Classes", it creates corresponding controller classes for each of the entities. That's where you'll need to make the changes noted above.

I don't remember which version of NB I was using at the time...maybe 7.1 or 7.2?

Hope this helps!

Mark

Posted by Mark Heckler on January 23, 2014 at 02:35 PM PST #

Ahh you were generating JSF Pages, I have been trying to generate "Session Beans for Entity Classes" and I just figured out why mine has not been working, It seems to be ok if i leave the table id the default value (null Integer) rather than setting to zero. My problem was that I was expecting the Entity to update the table id after the persist call - and since I was trying to use that table Entity to write to another table that used it's id as a foreign key the whole database call was failing.

Thanks for the response.

Posted by Neil Hall on January 23, 2014 at 06:17 PM PST #

Hi Neil,

Glad it worked out! Sorry for this (second) response being so late; for some reason, I wasn't notified there was a pending comment and just now ran across it. :O

Keep coding!
Mark

Posted by Mark Heckler on April 01, 2014 at 06:26 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

The Java Jungle addresses topics from mobile to enterprise Java, tech news to techniques, and anything even remotely related. The goal is to help us all do our work better with Java, however we use it.

Your Java Jungle guide is Mark Heckler, an Oracle Java/Middleware/Core Engineer with development experience in numerous environments. Mark's current work pursuits and passions all revolve around Java and leave little time to blog or tweet - but somehow, he finds time to do both anyway.

Mark lives with his very understanding wife, three kids, and dog in the St. Louis, MO area.



Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today