0

I'm building a Tomcat app using MySQL. I'm using a DAO pattern to talk to the database. I'm having trouble with where to initialize fields within the objects.

Mostly to save typing... I am using EclipseLink JPA to Generate model Entities from Tables. I am writing the DAO code by hand. I was writing the model by hand but this seemed easier.

The problem I am having is with writing the object back to the database will all the default nulls. For example, this table contains a bunch of id columns. Not all of them have context for every instance of the object. It seems inefficient to create the object and have to set all the fields to zero in order to be ale to save them to the database. If they have not context, I'd like to just leave them alone. i.e. I only want to set the fields that have context for what I am doing at that moment.

It seems best to use use the constructor in the model class to initialize them. But if I do that, EclipseLink will overwrite them the next time I generate the model.

Having the DAO update method check for nulls and set them to zero seems like a kludge. I suppose I could also use a factory to create and initialize the model class.

But I wonder if I am over thinking this... Any of these solutions would work. But there must be an accepted pattern for this.

How should I approach it?

Thanks

Model is just getters and setters. Contructor is empty.

Excerpts of code are below...

Notice notice = new Notice();
notice.setEvent("Welcome");
notice.setUserid(user.getId());
noticeDao.updateNotice(notice);

DAO:

//this seems inefficient
if(notice.getTravid() == null) notice.setTravid(0L);
if(notice.getBusid()  == null) notice.setBusid(0L);
if(notice.getSaveid() == null) notice.setSaveid(0L);
if(notice.getTargid() == null) notice.setTargid(0L);
if(notice.getTestmode() == null) notice.setTestmode(false);

String SQLupdate = "UPDATE notices SET "
                + "userid = ?, "
                + "travid = ?, "
                + "busid = ?, "
                + "saveid = ?, "
                + "targid = ?, "
                + "testmode = ?, "
                + "event = ?, "
                + "status = ?, "
                + "error = ?, "
                + "created = ?, "
                + "modified = ?, "
                + "log = ? "
                + "WHERE id = ?";
ps = conn.prepareStatement(SQLupdate);          
    ps.setLong(1, notice.getUserid());
    ps.setLong(2, notice.getTravid());
    ps.setLong(3, notice.getBusid());
    ps.setLong(4, notice.getSaveid());
    ps.setLong(5, notice.getTargid());
    ps.setBoolean(6, notice.getTestmode());
    ps.setString( 7, notice.getEvent());
    ps.setString( 8, notice.getStatus());
    ps.setString( 9, notice.getError());
    ps.setObject(10, notice.getCreated());
    ps.setObject(11, notice.getModified());
    ps.setString(12, notice.getLog());
    ps.setLong(  13, notice.getId());
    ps.executeUpdate();

DB:

CREATE TABLE `notices` (
  `id` int(20) unsigned NOT NULL AUTO_INCREMENT,
  `userid` int(20) unsigned NOT NULL DEFAULT '0',
  `travid` int(20) unsigned NOT NULL DEFAULT '0',
  `busid` int(20) unsigned NOT NULL DEFAULT '0',
  `saveid` int(20) unsigned NOT NULL DEFAULT '0',
  `targid` int(20) unsigned NOT NULL DEFAULT '0',
  `testmode` tinyint(1) DEFAULT '0',
  `event` varchar(40) DEFAULT NULL,
  `status` varchar(20) DEFAULT 'Pending',
  `error` varchar(255) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  `log` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8

The database table is like this:

ID

Generically, the code looks like this:

PrecisionPete
  • 3,139
  • 5
  • 33
  • 52

2 Answers2

0

Just to address your specific question, isn't there a way to tell eclipselink to set default values of the fields?

But there may be a deeper problem, with your database design. Are the *id fields not foreign key? They should be. And if they are foreign keys, then their value in database should be null, not 0L for rows where the specific fields do not have context.

At even deeper lever, if most of them don't have context in most rows -- that is, not being in context is an exception rather then norm -- then perhaps your database design itself is not good. You might be designing a universal table and will benefit from breaking the single table into multiple.

Miserable Variable
  • 28,432
  • 15
  • 72
  • 133
  • It seems there is not a way to tell EclipseLink to set the default values. That would of course be ideal. And I can't do it in the database as the row does not exist yet. I have no problem with them being null if they are not in context. But I can't write the default nulls back to the database without generating an exception. Or without writing lots of kludgy logic. In terms of design, I know I am cheating. To improve scalability, I am recording redundant ids in order to have fewer or less complex joins. To live on smaller hosting. – PrecisionPete Jan 30 '14 at 03:15
  • In this case what I am trying to do is have a queue of event based emails to send. e.g. if a new user signs up, it creates a row with event="new user" and records the userid. Then a scheduled job will send them a welcome email. If a user applies for a position, it created event="new applicaiton" and records the appid etc... If there is a better pattern for this I am interested. This is a bit messy. – PrecisionPete Jan 30 '14 at 03:20
  • I should add that I am limited in using foreign keys because some of my tables need to be MyISAM in order to use the full text search. This is a prototype so I had planned on cleaning this all up later. – PrecisionPete Jan 30 '14 at 03:32
0

Thanks for the great input. The solution I settled on was just to use the generic setObject for all data types. i.e.

ps.setLong(1, notice.getUserid());

becomes

ps.setObject(1, notice.getUserid());

MySQL seems perfectly happy with that. NULLs are not a problem. And it's a lot less work.

PrecisionPete
  • 3,139
  • 5
  • 33
  • 52