Observer Pattern and DAO Classes with Static CRUD Methods

I am looking at some DAO classes where they expose static CRUD methods create (), delete (), etc. into the program and where each DAO class implements the Observer pattern, checking for changes in the database via notification. java, and if one change notification is received by pulling the object from the database.

The simplified code looks like this:

OfficeDAO.java

public class OfficeDAO implements PropertyChangeListener
{
    public OfficeDAO()
    {
        /* 
         * Below we add ourselves to the observers of class Notifications
         * (see observer pattern in Java) in practice we are notified
         * when one of our objects is changed by a remote client user
         */
        Notification.addChangeListener(this);
    }

    public static void create(Office office)
    {
      Connection connection = DBConnection.getConnection();

      //... stuff with the database insertion

      Notification.notifyDatabaseChanges("ocreate-" + officeId);
    }
}

      

Now the problem is that addChangeListener (this); is in the constructor, but because this DAO class is used through its static methods, the constructor is never called.

To fix this in the main () method of the application (inside the EDT stream by the way) there is a call like:

new OfficeDAO(); //ignore this, it is needed only to start the DAO constructor

      

It seemed pretty hacky, so I thought to add

static {
  Notification.addChangeListener(this);
}

      

in the OfficeDAO.java class, but of course the "this" reference is missing in the static initializer, so I have no solutions. Removing static from DAO methods eliminates questions because those methods are called throughout the application and called without an instance of the class.

Is there any clean solution or workaround that I can't see right now?

+3


source to share


3 answers


DAO design is a very difficult question, you can start reading Balusc's article on DAO design and end up choosing a framework that deals with DAO and connection management.

A very subtle library that gives you a good start to properly implementing DAO, Butterfly Saving , it will create a DAOFactory and handle the connection for you without having to import the 100MB Spring or Hibernate banner library.



As far as adding listeners and notifications for database operations, you should avoid this entirely and instead use a database that supports event notification, such as Oracle or Firebird.

This way you only listen for events and the database notifies you of any changes to its tables.

0


source


This seems like a pretty messy scenario, creating a new object just to add a listener to the notification seems to be more of an anti-pattern. My guess is that this is part of some legacy code and there isn't much re-factoring of the code. I could say that since the DAO layer acts more like a singleton, you can inline a pre-instantiated DAO instance and access it via a static link.



private static OfficeDAO myDAO = new OfficeDAO(); //The constructor code remains the same

      

+2


source


You can change all DAO classes to Singleton. I agree that there is no need to instantiate the DAO since your DAOs are stateless and this is not a perfect solution. But then again, you are not looking for the perfect solution, but a cleaner hack with the minimum changes required in the client code. I'm not sure if you are using IoC framework in your project, but if you decide to use it in the future, converting DAO to Singleton will set the foundation for this.

Convert OfficeDAO to Singleton:

public class OfficeDAO implements PropertyChangeListener {

    private static volatile OfficeDAO INSTANCE;

    private OfficeDAO() {
        if (INSTANCE != null) {// prevent reflection attacks
            throw new InstantiationError("Illegal attempt to create more than one instance of OfficeDAO");
        }
        Notification.addChangeListener(this);
    }

    public static OfficeDAO getInstance() {
        OfficeDAO localInstance = INSTANCE;
        if (INSTANCE == null) {
            synchronized (OfficeDAO.class) {
                localInstance = INSTANCE;
                if (localInstance== null) {
                    INSTANCE = localInstance = new OfficeDAO();
                }
            }
        }
        return localInstance;
    }

    public void create(Office office) {
        Connection connection = DBConnection.getConnection();

        // ... stuff with the database insertion

        Notification.notifyDatabaseChanges("ocreate-" + officeId);
    }
}

      

If you change all of your DAOs in the same way, the only change you will need to make to the client code is to change ClassName.staticMethod()

to ClassName.getInstance().staticMethod()

.

Example: OfficeDAO.getInstance().create(..)

* Assuming that your observers are also subjects, and this is not the classic way to implement the Observer pattern. Alternatively, you can avoid double check blocking and resort to a singleton that is not lazy to create. How you implement the Singleton is a matter of your choice and not directly related to the question.

If your project starts to use an Ioc framework like Spring or Guice, you can get rid of the private constructor and getInstance method. Your best bet would be to change all static methods in the DAO to instance methods and create an IoC framework and inject the DAO into all the classes that require them. This has several advantages:

  • Most IoC frameworks allow you to decide whether only one object of a class should be provided on request, or new objects should be provided every time one is requested. Therefore, you can choose between Singleton vs non Singleton DAOs without having to change your DAOs.
  • Your data source can change from database to CSV file, and you don't have to change the client code that DAO uses.
  • Actually you can mock your DAO in unit test service classes.
0


source







All Articles