> The issue is that I am getting a weird error when I try to create the first dao.
>
> Exception in thread "main" java.lang.IllegalArgumentException: Generated-id field 'id' in Place can't be type LONG. Must be one of: INTEGER INTEGER_OBJ LONG LONG_OBJ UUID
Ok. SQLite requires generated-id fields to be integers, not longs.
> Of course, when I remove the call to registerDataPersisters it works fine !
Wow. I certainly don't understand that. Is your JodaTime your id field? Can you show us your data type with the id field?
> I am a bit puzzled : the message is obviously wrong or there is a tricky side effect I fail to understand :)
Agreed. I'm puzzled as well.
> Just for reference, here's the code of the JodaTimePersister :
The persister really should have nothing to do with it.
> private JodaTimePersister() {
> super(SqlType.LONG, new Class[] { DateTime.class });
> }
Aha. So I think the first argument to the super() should be null. What you are saying with the LONG is that all Long types should be persisted by this persister. That may be confusing matters. All you need is:
super(null, new Class[] { DateTime.class });
Long value = results.getLong(columnPos);
getLong returns a lowercase l long so it will never be null. You should use the wasNull() boolean after the fact. That (unfortunately) is how JDBC works.
gray
> By the way, are the custom persisters available for Android as well ?
> Performance wise, would you recommend using them on the constrained Android environment ?
They are available the same way as under JDBC. I see no performance ramifications of using custom persisters unless the persister code itself is an issue.
gray
>> private JodaTimePersister() {
>> super(SqlType.LONG, new Class[] { DateTime.class });
>> }
>
> Aha. So I think the first argument to the super() should be null. What you are saying with the LONG is that all Long types should be persisted by this persister. That may be confusing matters. All you need is:
No, this is completely wrong. Cancel that. Your LONG is correct. That's the how it is represented in SQL land.
I don't have any idea why you are having the problems you are having. If you respond with your data class maybe that will shed some light on the subject.
gray
> Is there a tutorial or anything on how to go about writing a custom
> persister? I don't see anything via googling. I could look at the
> source for existing persisters, but there are such nice docs on just
> about everything else to do with this library, that I figured it was worth asking.
Unfortunately not. I've spent a TON of time on the docs but still some of the more advanced features do not get mentioned. Custom persisters is one such area. It's already in the TODO list to add the docs. Feel free to write up your experience and I'll put it into the manual.
In the meantime, the quick recipe is:
1) You will probably want to extend BaseDataType and then override the specific methods that you want. The parseDefaultString, resultToJava, and isValidForField methods are the required methods you need to override. isValidForField won't be required in 4.34.
2) Take a look at StoredClassPersister in DataPersisterManagerTest. That gives a good starting place: http://goo.gl/upCSc
Let me know if you have any questions directly khaavren and it will help to flesh out the docs.
gray
> Thanks for the pointers. Got it working!
> Here's the gist:
> https://gist.github.com/1b708ba702bdf9268d48
Looks good. Couple of comments:
1) Instead of overriding getSqlType, just pass ing SqlType.LONG as the first argument of the persister. I found and fixed that pattern in the code/tests.
2) You could obviously support a default string with on of the JodaTime parsers.
3) I've refactored some of the BaseDataType stuff a bit so watch for some tweaks in 4.34. Sorry about that but it's an internal improvement. It changes resultToJava to be resultToSqlArg and then it has a impl of resultToJava which calls resultToSqlArg and sqlArgToJava itself. That was the pattern used by 80+% of the data types. You also would not need your isValidForField() method because that's been improved in BaseDataType. You resultToSqlArg would then be:
public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int columnPos) throws SQLException {
return results.getLong(columnPos);
}
4) You don't need the singleton pattern. That's only for types that are built in.
gray
> As Joda is used by a considerable number of people it would be great if this solution could be hosted somewhere and perfected!
As I just posted, I've added a default handler for DateTime that uses reflection. Since it is using reflection then it can't detect the field directly and you have to turn it on with:
@DatabaseField(dataType = DataType.DATE_TIME)
private DateTime dateTime;
You can also do:
DataPersisterManager.register
gray
Would it better to make an ormlite-jodatime package that has a real
dependency on joda time? And continue that pattern as other optional
persisters are added?
~Craig
> I'm curious if using reflection is really best approach. Writing (and
> testing) reflection code is challenging for one thing, so maintenance is a problem.
I think it is a good approach or I wouldn't have added it. :-)
I would doubt that DateTime is changing very much of a class. Right now I'm using 1 method (toMillis()) and 1 constructor from it so I doubt this is an issue. Testing is pretty easy as long as I have the DateTime class in my test class path.
> Secondly, this solution makes things less "automatic" than they
> could be - for example, because reflection is used, it can't detect the
> field directly.
This would be the case no matter what. Come to think of it, I guess I could do auto detection of DateTime if I see a DateTime field. Duh. I'll add this to the TODO file.
> Would it better to make an ormlite-jodatime package that has a real
> dependency on joda time? And continue that pattern as other optional
> persisters are added?
If you want to set one up then go ahead. Unfortunately, it takes more than an insignificant amount of time to maintain the 3 packages I have. Another one just for jodatime would not be a good idea but some sort of ormlite-utility package with some other classes would be good.
gray