As MyBatis is a basic ORM, when we need to persista list of objects, we have to implement it manually, but without any copy/paste between classes. For this purpose, I designed a generic merger which is responsible of that task.
It has to go through a list of objects and determine:
- what is new and needs to be created
- what is not there meaning it has been deleted
- what was already here and needs to be updated
To identify in which case we are, we need to provide it a java.util.Comparator and also a Dao to be able to interact with the database.
This is done in one main class (which uses also what I described in a previous post)
package net.classnotfound.data.dao.utils; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.List; import net.classnotfound.capability.Identifiable; import net.classnotfound.data.dao.Dao; /** * This class is used to merge a list with another list. It is helpful when we need to marge a list of elements * which come from the GUI with the list in the database * @author roussehe * * @param <T> the type of element we have to manage */ public class MergerList<T extends Identifiable> { private Dao<T> dao; private Finder<T> finder; /** * * @param dao the dao used to merge the new or existing entries and to delete the removed ones * @param comparator the comparator used to know if an element already exists in the DB */ public MergerList(Dao<T> dao, Comparator<T> comparator) { super(); this.dao = dao; this.finder = new Finder<>(comparator); } /** * merge the 2 lists, making comparison between existing/new/removed entries and persist the data in the database * @param oldEntryList the list coming from the db (usually) * @param newEntryList the new list we need to persist */ public void mergeList(List<T> oldEntryList, List<T> newEntryList) { List<T> mergedEntries = new ArrayList<>(); List<T> deletedEntries = new ArrayList<>(); //we have to go through the 2 lists and check it one by one if(oldEntryList!=null&& !oldEntryList.isEmpty()) { //here, we check the entries which are present or not in the old list for (T entry : oldEntryList) { T found = finder.findMember(entry, newEntryList); if (found!=null) {//if found, we have to update it mergedEntries.add(found); } else {//not found means it must be deleted from db deletedEntries.add(entry); } } } if(newEntryList!=null&& !newEntryList.isEmpty()) { //here we check the entries which are only present in the new list for (T entry : newEntryList) { T found = finder.findMember(entry, oldEntryList); if(found == null) {//if not found in db, it's a new entry mergedEntries.add(entry); }//if found, it is already managed in the previous loop } } //process records deleteEntries(deletedEntries); mergeEntries(mergedEntries); } /** As my Dao can manage create and update, it is done in one time. * @param mergeEntries */ private void mergeEntries(List<T> mergeEntries) { for (T t: mergeEntries) { dao.merge(t); } } private void deleteEntries(Collection<T> deletedItems) { for (T t: deletedItems) { dao.delete(t); } } /** * This class is a helper class to find an object in a list of items * * @param <R> */ private class Finder<R>{ private Comparator<R> comp; Finder(Comparator<R> comp) { super(); this.comp = comp; } /** * This method is responsible of getting object from the provided list. * @param entry * @param list * @return the object if found, or null otherwise */ R findMember(R entry, List<R> list) { R found = null; if(list!=null&&!list.isEmpty()) { for (Iterator<R> iterator = list.iterator(); iterator.hasNext()&&found==null;) { R currEntry = iterator.next(); if(comp.compare(entry, currEntry)==0) found = currEntry; } } return found; } } }
Done 😀