Repository Pattern with Repository Factory - java

I'm trying to improve my Android persistence layer to be used across multiple applications.
What i have done so far is to setup a base repository abstract class and also a base repository interface, the complete code can be check here: https://github.com/grmaciel/android-repository-ormlite
Interface:
public interface IRepository<T, Id> {
public void save(T entity) throws SQLException;
public void saveBatch(List<T> entities) throws Exception;
public List<T> queryAll() throws SQLException;
public T findById(Id id) throws SQLException;
public void delete(T entity) throws SQLException;
}
Now all my repositories extends my base repository, like this:
public class DependencyRepository extends BaseRepository<Dependency>
implements IDependenceyRepository {
public DependencyRepository(Context context) {
super(context);
}
}
What i'm trying to achieve now is to create a repository factory that would allow people to not have to instantiate their repositories all over the place with the new Instance()
What i did was to create a Singleton factory that has to be initialized with a container that has the class relations, like this:
public abstract class BaseRepositoryContainer {
private final Context context;
public BaseRepositoryContainer(Context context) {
this.context = context;
}
public abstract <T extends IRepository> Map<Class<T>, Class<T>> getRepositoriesMap();
public Context getContext() {
return context;
}
}
The factory:
public class RepositoryFactory {
private Map<Object, Object> repositories = new HashMap<>();
private final String LOG_TAG = RepositoryFactory.class.getSimpleName();
private Context context;
private static RepositoryFactory instance;
private BaseRepositoryContainer container;
private RepositoryFactory() {}
public void init(BaseRepositoryContainer container) {
this.container = container;
this.context = container.getContext();
this.configureRepositories(container.getRepositoriesMap());
}
private <T extends IRepository> void configureRepositories(Map<Class<T>, Class<T>> repositoriesMap) {
for (Entry<Class<T>, Class<T>> entry : repositoriesMap.entrySet()) {
this.registerRepository(entry.getKey(), entry.getValue());
}
}
private <T extends IRepository> void registerRepository(Class<T> repInterface, Class<T> realRepository) {
repositories.put(repInterface, this.createRepository(realRepository));
}
public <T extends IRepository> T getRepository(Class<T> repInterface) {
if (container == null) {
throw new UnsupportedOperationException("You should call init method providing a container.");
}
return (T) repositories.get(repInterface);
}
private <T extends IRepository> T createRepository(Class<T> repoClass) {
try {
T instance = repoClass.getConstructor(Context.class).newInstance(context);
Log.d(LOG_TAG, "Repository " + repoClass.getSimpleName() + " created");
return instance;
} catch (InstantiationException e) {
Log.d(LOG_TAG, e.toString());
} catch (IllegalAccessException e) {
Log.d(LOG_TAG, e.toString());
} catch (InvocationTargetException e) {
Log.d(LOG_TAG, e.toString());
} catch (NoSuchMethodException e) {
Log.d(LOG_TAG, e.toString());
}
return null;
}
public static RepositoryFactory getInstance() {
if (instance == null) {
instance = new RepositoryFactory();
}
return instance;
}
}
And then it could be called like this:
// when the application is first run
RepositoryFactory.getInstance().init(new RepositoryContainer(this));
// retrieving the repository
IDependenceyRepository repository = RepositoryFactory.getInstance()
.getRepository(IDependenceyRepository.class);
So i was wondering if is this a good approach to help to implement towards an abstraction? I don't like much the idea of to have the calling the init method of the factory without obligating people to it, the only way to know is if you dont call will throw an exception which i dont like.
Does anyone can point me the right direction? A way to improve this design? I dont want to discover later on my project that i have created lots of strong dependencies and have a hard time to change something.
Any advices would be appreciated.

What i did to improve my code was instead of reinventing the wheel i started using a dependency injection library (Dagger 2 - http://google.github.io/dagger/).
You can define modules that return your desidered repository across an application or activities depending on your needs.

Related

Register BeanFactory in SpringBoot

First I'm not sure if it's a good idea to do all this.
Goal is to create some interfaces with annotations to hide legacy position based string access out of a configuration database, without implementing each interface.
Declarative configured Interface:
public interface LegacyConfigItem extends ConfigDbAccess{
#Subfield(length=3)
String BWHG();
#Subfield(start = 3, length=1)
int BNKST();
#Subfield(start = 4, length=1)
int BEINH();
:
}
Base interface for runtime identification
public interface ConfigDbAccess{
}
Dummy implementation without functionality, may change.
public class EmptyImpl {
}
Beanfactory and MethodInvocation interceptor, to handle the unimplemented methods.
#Component
public class InterfaceBeanFactory extends DefaultListableBeanFactory {
protected static final int TEXT_MAX = 400;
#Autowired
private EntityRepo entityRepo;
public <T> T getInstance(Class<T> legacyInterface, String key) {
ProxyFactory factory = new ProxyFactory(new EmptyImpl());
factory.setInterfaces(legacyInterface);
factory.setExposeProxy(true);
factory.addAdvice(new MethodInterceptor() {
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
KEY keyAnnotation = invocation.getThis().getClass().getAnnotation(Key.class);
String key= keyAnnotation.key().toUpperCase();
String ptart = invocation.getMethod().getDeclaringClass().getSimpleName();
Vpt result = entityRepo.getOne(new EntityId(ptart.toUpperCase(), schl.toUpperCase()));
Subfield sub = invocation.getMethod().getAnnotation(Subfield.class);
//TODO: Raise missing Subfield annotation
int start = sub.start();
int length = sub.length();
if (start + length > TEXT_MAX) {
//TODO: Raise invalid Subfield config
}
String value = result.getTextField().substring(start,start+length);
return value;
}
});
return (T) factory.getProxy();
}
#Override
protected Map<String, Object> findAutowireCandidates(String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
Map<String, Object> map = super.findAutowireCandidates(beanName, requiredType, descriptor);
if (ConfigDbAccess.class.isAssignableFrom(requiredType )) {
:
#SpringBootApplication
public class JpaDemoApplication {
#Autowired
private ApplicationContext context;
public static void main(String[] args) {
SpringApplication app = new SpringApplication(JpaDemoApplication.class);
// app.setApplicationContextClass(InterfaceInjectionContext .class);
app.run(args);
}
public class InterfaceInjectionContext extends AnnotationConfigApplicationContext {
public VptInjectionContext () {
super (new InterfaceBeanFactory ());
}
}
So far I got all this stuff working, except when I try to set the applications Context class to my DefaultListableBeanFactory, I'm killing the Spring boot starter web. The application starts, injects the the Autowired fields with my intercepted pseudo implementaition --- and ends.
I think I'm doing something wrong with registering the DefaultListableBeanFactory, but I've no idea how to do it right.
To get this answered:
M. Deinum pointed me to a much simpler solution:
Instead of creating a BeanFactory I installed a BeanPostProcessor with this functioniality.
#RestController
public class DemoRestController {
#Autowired
VptService vptService;
#ConfigItem(key="KS001")
private PrgmParm prgmKs001;
#ConfigItem(key="KS002")
private PrgmParm prgmKs002;
public DemoRestController() {
super();
}
Where the ConfigItem annotation defines the injection point.
Next I created a CustomBeanPostProcessor which scans all incoming beans for
fields having a ConfigItem annotation
#Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
for (Field field : bean.getClass().getDeclaredFields()) {
SHL cfgDef = field.getAnnotation(ConfigItem.class);
if (cfgDef != null) {
Object instance = getlInstance(field.getType(), cfgDef.key());
boolean accessible = field.isAccessible();
field.setAccessible(true);
try {
field.set(bean, instance);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
field.setAccessible(accessible);
}
}
return bean;
}
The getInstnce(field.getType(),cfgDef.key()) creates a proxy with the MethodInterceptor, which does the work.
There are a lot of things to finalize, but all in all it looks good to me.

How generify class with T and List<T>

I am trying to generify my class structure.
I will show my real structure to be more specific.
I am writing application with offline mode support, so I decided to implement my ETag cache mechanism in using Robospice and GreenDao ORM.
I need to cache only GET requests.
Firstly my requests should extend base request(not mine), in my case RetrofitSpiceRequest<T, V>
T is type of return data
V is service type, in my case I am using Retrofit.
The problem is that return type is not List of T types by default and I need to create subclass that extends array of T objects and that use it as return type.
Something like this
public class City {
....
....
....
public static class List extends ArrayList<City> {
.....
.....
}
}
And use City.List as return type.
But I have my DAO declared as following
public class CityDao extends AbstractDao<City, Long> {
}
In each request (GET) I need to have specific DAO as a member in order to cache data if it differs from the server data. Or load data from the local database if there is no connection.
The problem here is that request generified by T type which is mostly list, City.List in my case, of some objects, but my dao is generified by, for example E type which is City in my case.
I want to create method like this
public AbastractDao<T,Long> getRequestDao() {
}
But as far as my Request returns City.List, I have no idea how to generify this class, I feel that it is possible, but now no ideas.
In case of non generic dao method, I have to duplicate code like this
#Override
public void insertReceivedData(City.List received) {
mCityDao.insertOrReplaceInTx(received);
}
#Override
public City.List getCachedData() {
if (mFilterMap != null && mFilterMap.size() > 0) {
return (City.List) mCityDao.loadAll();
} else {
WhereCondition[] whereConditions = QueryUtils.convertPropertyMapToConditionalArray(mFilterMap);
return (City.List) mCityDao.queryBuilder().where(whereConditions[0], Arrays.copyOfRange(whereConditions, 1, whereConditions.length)).list();
}
}
In each request
Please share your ideas.
Thanks.
I end up with following solution. It is not as good as I wanted, but it works and better than duplicating code.
My base request class.
public abstract class BaseGetRequest<L extends List<T>, T, V> extends RetrofitSpiceRequest<L, V> implements FilterableRequest {
// Context
protected Context mContext;
// Filter used in request and in queries
protected Map<Property, String> mFilterMap;
// Session provided Singletone
protected DaoSessionProvider mSessionProvider;
public BaseGetRequest(Class<L> clazz, Class<V> retrofitedInterfaceClass, Context context, Map<Property, String> filterMap) {
super(clazz, retrofitedInterfaceClass);
mContext = context;
mFilterMap = filterMap;
mSessionProvider = ((DaoSessionProvider) mContext.getApplicationContext());
// TODO determine required retry count
setRetryPolicy(new RetryPolicy() {
#Override
public int getRetryCount() {
return 0;
}
#Override
public void retry(SpiceException e) {
}
#Override
public long getDelayBeforeRetry() {
return 0;
}
});
}
protected WhereCondition[] getWhereConditions() {
return QueryUtils.convertPropertyMapToConditionalArray(mFilterMap);
}
public BaseGetRequestV2(Class<L> clazz, Class<V> retrofitedInterfaceClass, Context context) {
this(clazz, retrofitedInterfaceClass, context, null);
}
public abstract AbstractDao<T, Long> getDao();
public abstract L createDataList(List<T> list);
public L getCachedData() {
if (mFilterMap != null && mFilterMap.size() > 0) {
WhereCondition[] whereConditions = getWhereConditions();
return createDataList(getDao().queryBuilder().where(whereConditions[0], Arrays.copyOfRange(whereConditions, 1, whereConditions.length)).list());
} else {
return createDataList(getDao().loadAll());
}
}
public abstract L getData();
#Override
public Map<Property, String> getFilterMap() {
return mFilterMap;
}
public Map<String, String> getStringMap() {
return QueryUtils.convertPropertyMapToString(mFilterMap);
}
#Override
public L loadDataFromNetwork() throws Exception {
L receivedData = null;
try {
receivedData = getData();
WhereCondition[] conditions = getWhereConditions();
getDao().queryBuilder().where(conditions[0],Arrays.copyOfRange(conditions, 1, conditions.length)).buildDelete().executeDeleteWithoutDetachingEntities();
getDao().insertOrReplaceInTx(receivedData);
} catch (Exception ex) {
receivedData = getCachedData();
}
return receivedData;
}
}
And I can extend this class like so:
public class NewsRequest extends BaseGetRequest<NewsArticle.List, NewsArticle, API> {
public static final String TARGET_URL = "/news";
NewsArticleDao mNewsArticleDao;
public NewsRequest(Context context) {
this(context, null);
}
public NewsRequest(Context context, Map<Property, String> filterMap) {
super(NewsArticle.List.class, API.class, context, filterMap);
mNewsArticleDao = mSessionProvider.getDaoSession().getNewsArticleDao();
}
#Override
public AbstractDao<NewsArticle, Long> getDao() {
return mNewsArticleDao;
}
#Override
public NewsArticle.List createDataList(List<NewsArticle> list) {
return new NewsArticle.List(list);
}
#Override
public NewsArticle.List getData() {
return getService().getNews(getStringMap());
}
}

What is the best way to create configurable object repository in java?

To explain more, what I want is to identify the incoming request based on some parameters in a client server arch. Suppose I receive a request on server which has some parameters like command=xyz, param1=blah, param2=blah2.
some.property.xyz=com.domain.BusinessFunction1
some.property.abc=com.domain.BusinessFunction2
Now after identifying these parameters, and looking at configurations, i should be able to call the right business function, as in above example, if I received a request in which command param is xyz, it should go through BusinessFunction1 else if it is abc it should go through BusinessFunction2. And BusinessFunction1 and BusinessFunction2 are implemented in two different Java classes.
Your best approach is to create a singleton factory, which you can populate from a database com.domain.BusinessFunction1 stored against the service name some.property.xyz. The factory will use reflection to construct the class by using Class.forName("com.domain.BusinessFunction1"); then you can call a method on this class which takes for ease of use sake a map of property names and values. Personally I'd create another factory and have specific objects for each business function. If you don't have a database you could store the name value of the business function in an XML or an enum.
Here is the idea using a Singleton and a HashMap. I would suggest you populate the factory from a database to give you more flexibility.
A generic base interface
public interface IBusinessFunction {
public void doFunction();
public void setParameters(Map<String,String> paramMap);
}
The Business functions
public class BusinessFunction1 implements IBusinessFunction {
#Override
public void doFunction() {
System.out.println(String.format("Function from business class %s called.", this.getClass().getName()));
}
#Override
public void setParameters(Map<String, String> paramMap) {
}
}
public class BusinessFunction2 implements IBusinessFunction {
#Override
public void doFunction() {
System.out.println(String.format("Function from business class %s called.", this.getClass().getName()));
}
#Override
public void setParameters(Map<String, String> paramMap) {
}
}
BusinessFactory
public class BusinessFactory {
private static BusinessFactory instance = null;
private Map<String, Class<? extends IBusinessFunction>> businessFunctionMap = null;
protected BusinessFactory() {
// Populate this from a database,
// for the ease of your example i will use a HashMap
businessFunctionMap = new HashMap<String, Class<? extends IBusinessFunction>>();
businessFunctionMap.put("some.property.xyz", BusinessFunction1.class);
businessFunctionMap.put("some.property.abc", BusinessFunction2.class);
}
public static BusinessFactory getInstance() {
if (instance == null) {
instance = new BusinessFactory();
}
return instance;
}
public IBusinessFunction getBusinessFunction(String property) {
IBusinessFunction businessFunction = null;
Class clazz = businessFunctionMap.get(property);
try {
Constructor constructor = clazz.getConstructor();
businessFunction = (IBusinessFunction) constructor.newInstance();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return businessFunction;
}
}
Test your class and factory
public class Example {
public static void main(String[] args) {
Map<String,String> parameters = new HashMap<String, String>();
parameters.put("Param1","param 1 value");
parameters.put("Param2","param 2 value");
IBusinessFunction businessFunction = BusinessFactory.getInstance().getBusinessFunction("some.property.abc");
businessFunction.setParameters(parameters);
businessFunction.doFunction();
}
}

Java - Execute a class method with a specify annotation

I have a android application, but it is not relevant.
I have a class called "Front controller" which will receive some message
through it's constructor. The message, for brievity, could be an integer.
I want somewhere else to create a new controller which will execute
a method based on the integer defined above
public class OtherController {
#MessageId("100")
public void doSomething(){
//execute this code
}
#MessageId("101")
public void doSomethingElse(){
//code
}
}
The front controller could be something like this:
public class FrontController {
private int id;
public FrontController(int id){
this.id=id;
executeProperControllerMethodBasedOnId();
}
public void executeProperControllerMethodBasedOnId(){
//code here
}
public int getId(){
return id;
}
}
So, if the Front Controller will receive the integer 100, it
will execute the method annotated with #MessageId(100). The
front controller don't know exactly the class where this method
is.
The problem which I found is that I need to register somehow
each controller class. I Spring I had #Component or #Controller
for autoloading. After each controllers are register, I need to
call the properly annotated method.
How to achieve this task? In Spring MVC, I had this system
implemented, used to match the HTTP routes. How could I implement
this in a plain java project?
Any suggestions?
Thanks to Google Reflections (hope you can integrate this in your android project.)
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections-maven</artifactId>
<version>0.9.8</version>
</dependency>
For optimisation I've added the requirement to also annotate the class with MessageType annotation and the classes should be in the same package (org.conffusion in my example):
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface MessageType {
}
The OtherController looks like:
#MessageType
public class OtherController {
#MessageId(id=101)
public void method1()
{
System.out.println("executing method1");
}
#MessageId(id=102)
public void method2()
{
System.out.println("executing method2");
}
}
The implementation will look like:
public void executeProperControllerMethodBasedOnId() {
Set<Class<?>> classes = new org.reflections.Reflections("org.conffusion")
.getTypesAnnotatedWith(MessageType.class);
System.out.println("found classes " + classes.size());
for (Class<?> c : classes) {
for (Method m : c.getMethods()) {
try {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
Object o = c.newInstance();
if (mid.id() == id)
m.invoke(o);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Maybe you can optimise and build a static hashmap containing already scanned message ids.
You need to implement some of the work by yourself using reflection, I would recommend to prepare message handlers on initial phase in regards to performance. Also you possibly want to think about Singleton/Per Request controllers. Some of the ways to implement the solution:
interface MessageProcessor {
void execute() throws Exception;
}
/* Holds single instance and method to invoke */
class SingletonProcessor implements MessageProcessor {
private final Object instance;
private final Method method;
SingletonProcessor(Object instance, Method method) {
this.instance = instance;
this.method = method;
}
public void execute() throws Exception {
method.invoke(instance);
}
}
/* Create instance and invoke the method on execute */
class PerRequestProcessor implements MessageProcessor {
private final Class clazz;
private final Method method;
PerRequestProcessor(Class clazz, Method method) {
this.clazz = clazz;
this.method = method;
}
public void execute() throws Exception {
Object instance = clazz.newInstance();
method.invoke(instance);
}
}
/* Dummy controllers */
class PerRequestController {
#MessageId(1)
public void handleMessage1(){System.out.println(this + " - Message1");}
}
class SingletonController {
#MessageId(2)
public void handleMessage2(){System.out.println(this + " - Message2");}
}
class FrontController {
private static final Map<Integer, MessageProcessor> processors = new HashMap<Integer, MessageProcessor>();
static {
try {
// register your controllers
// also you can scan for annotated controllers as suggested by Conffusion
registerPerRequestController(PerRequestController.class);
registerSingletonController(SingletonController.class);
} catch (Exception e) {
throw new ExceptionInInitializerError();
}
}
private static void registerPerRequestController(Class aClass) {
for (Method m : aClass.getMethods()) {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
processors.put(mid.value(), new PerRequestProcessor(aClass, m));
}
}
}
private static void registerSingletonController(Class aClass) throws Exception {
for (Method m : aClass.getMethods()) {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
Object instance = aClass.newInstance();
processors.put(mid.value(), new SingletonProcessor(instance, m));
}
}
}
/* To process the message you just need to look up processor and execute */
public void processMessage(int id) throws Exception {
if (processors.containsKey(id)) {
processors.get(id).execute();
} else {
System.err.print("Processor not found for message " + id);
}
}
}

Is it good have a DatabaseManager with all of the functions from all the model objects?

I'working on a db application with ORmlite, my model is like this:
MDL object..
DatabaseTable(tableName = "UserCars")
public class CarMDL
{
#DatabaseField(generatedId = true)
private int _id;
#DatabaseField(columnName = "name")
private String _name;
//................. etc
}
// DB Helper class...
public class DatabaseHelper extends OrmLiteSqliteOpenHelper
{
private Dao<CarMDL,Integer> _carDao = null;
#Override
public void onCreate(SQLiteDatabase database,ConnectionSource connectionSource)
{
try
{
TableUtils.createTable(connectionSource, CarMDL.class);
} catch (SQLException e)
{
throw new RuntimeException(e);
} catch (java.sql.SQLException e)
{
e.printStackTrace();
}
}
public Dao<CarMDL, Integer> getCarDao()
{
if (null == _carDao)
{
try
{
_carDao = getDao(CarMDL.class);
}catch (java.sql.SQLException e)
{
e.printStackTrace();
}
}
return _carDao;
}
}
// DatabaseManager class...
public class DatabaseManager
{
static private DatabaseManager instance;
private DatabaseHelper helper;
static public void init(Context ctx)
{
if (null == instance)
{
instance = new DatabaseManager(ctx);
}
}
static public DatabaseManager getInstance()
{
return instance;
}
private DatabaseManager(Context ctx)
{
helper = new DatabaseHelper(ctx);
}
private DatabaseHelper getHelper()
{
return helper;
}
// All the Dao functions of all MDL objects are in this class, for example:
public List<CarMDL> getAllCars()
{
List<CarMDL> carLists = null;
try
{
carLists = getHelper().getCarDao().queryForAll();
} catch (SQLException e)
{
e.printStackTrace();
}
return carLists;
}
// This is another MDL object..
public List<MarkMDL> getAllMarks()
{
List<MarkMDL> marks = null;
try
{
marks = getHelper().getMarkDao().queryForAll();
} catch (SQLException e)
{
e.printStackTrace();
}
return marks;
}
}
So my question is, is it good have a DatabaseManager with all the functions from all the model objects, like:
listCarById(int id)
listPlaneById(int id)
removeCar(int id)
removePlane(int id)
Etc.....
Updated per Gray's comment.
Be careful with your "singleton" implementation. Your init method should be synchronized to ensure that you don't end up with multiple instances of your DatabaseManager class due to concurrency issues. I would just combine the init and getInstance methods to the following (note the added synchronized keyword):
public static synchronized DatabaseManager getInstance(Context c)
{
if(instance == null)
instance = new DatabaseManager(c);
return instance;
}
For further reading, check out these blog posts about Single SQLite Connection and Android Sqlite locking by Kevin Galligan (one of the contributors to ORMlite).
Update:
To answer your question about how to organize your loading methods like getAllCars, I would first suggest making them static, since they do not depend on anything else besides your method to get your singleton of DatabaseManager, which of course, would also be static. If you have a small number of these types of methods, you could make them all static members of DatabaseManger. If you have many, you could make a helper class for all static methods corresponding to a type.
If you have a method that does depend on the internals of a given instance of CarMDL or MarkMDL (like you need a method to get some associated references), consider making these methods members of the CarMDL or MarkMDL class.
I put all my one-time-per-app work in Application onCreate and I keep a reference of the application instance itself, so I can do many tasks without having to mess with synchronized methods or similar. So let's say we have an Application (remember to add it in the manifest):
public class App extends Application
{
private static App gInstance = null;
// your static globals here
#Override
public void onCreate()
{
// according to documentation onCreate is called before any other method
super.onCreate();
// assign here all your static stuff
gInstance = this;
}
// doesn't need to be synchronized because of the early onCreate
public static App getInstance()
{
return gInstance;
}
}
then your database helper class, Manifest.class is an array of all of your datatype classes:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper
{
// private constructor, singleton pattern, we use
// App context so the class is created on static init
private static DatabaseHelper gHelper = new DatabaseHelper(App.getInstance());
private DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION, R.raw.ormlite_config);
// cache your dao here
for (Class<?> cls: Manifest.classes)
{
try
{
DaoManager.createDao(getConnectionSource(), cls);
} catch (SQLException e)
{
e.printStackTrace();
}
}
}
// if you need the instance, you don't need synchronized because of static init
public static DatabaseHelper getHelper()
{
return gHelper;
}
// lookup from cache
public static <D extends Dao<T, ?>, T> D getTypeDao(Class<T> cls)
{
return DaoManager.lookupDao(gHelper.getConnectionSource(), cls);
}
// we leak this class here since android doesn't provide Application onDestroy
// it's not really a big deal if we need the orm mapping for all application lifetime
// Q: should I keep the instance closeable? the android finalyzer calls somehow close here? I was unable to reproduce, to be sure you can call the super.close() and print a warning
#Override
public void close()
{
throw new RuntimeException("DatabaseHelper Singleton is ethernal");
}
}
addd the context to your DatabaseManager method
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DatabaseManager.init(this.getContext());
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
example android app with ormlite
https://github.com/elberthcabrales/cfeMedicion

Categories