public abstract class BaseService<P, R extends Record> {
protected void create(P tableObject) {
R g = buildRecordObject(tableObject);
g.store();
}
protected void update(P tableObject) {
R g = buildGenericRecord(tableObject);
g.store();
}
protected void delete(P tableObject) {
R g = buildGenericRecord(tableObject);
g.delete();
}
protected P find(String slug) {
return dao().fetchOneBySlug(slug);
}
public List<R> list(int pageNumber) {
pager = new Page(count());
TABLE table = table();
RecordMapper genericMapper = mapper();
return sql.select()
.from(table)
.orderBy(table.CREATED_ON.desc())
.limit(pageSize)
.offset(pager.offsetFromPage(pageNumber))
.fetch(genericMapper);
}
// these would need to be provided by the subclass
protected abstract R buildRecordObject(P tableObject);
protected abstract TABLE table();
protected abstract BaseDao dao();
protected abstract RecordMapper mapper();
}--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "jOOQ User Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jooq-user/KUPyMa2581g/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jooq-user+...@googlegroups.com.
Hi Lukas,This is exactly what I was looking for, thank you for responding.Regarding just using org.jooq.DAO: I am using it where I can, but perhaps my lack of JOOQ knowledge is causing me to run into some issues. I think I ran into a few things, one being I wasn't sure how to get the query granularity for sorting, limiting and ordering that I wanted to using the DAO methods. I haven't looked at this specifically in a while, so I could very well be missing something.
So, my next questions are:1. What would you recommend if I were to implement this using just org.jooq.DAO? Again, I'll go off on my own and do some more research on the generated DAO methods, but I'd like some expert input.
2. What needs to be used in place of the TABLE object in my code example? I can see situations where I'll want to drop straight into jooq queries and it would be helpful to be able to do that without having to duplicate code.
The simplest way forward might be to extend the default DAOImpl and let the code generator use your custom DAOImpl as a base class using generator strategies:One option using generator strategies would be to implement "custom code sections", where you can add your own methods to the generated DAOs:Another option would be to extend the generated DAOs and add functionality on a per-table basis.But of course, your suggested option is fine, too.
--
You received this message because you are subscribed to a topic in the Google Groups "jOOQ User Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jooq-user/KUPyMa2581g/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jooq-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
The simplest way forward might be to extend the default DAOImpl and let the code generator use your custom DAOImpl as a base class using generator strategies:One option using generator strategies would be to implement "custom code sections", where you can add your own methods to the generated DAOs:Another option would be to extend the generated DAOs and add functionality on a per-table basis.But of course, your suggested option is fine, too.Extending the generated DAOs might not be so bad. I'll read up on what you've sent me, thanks!
In terms of my last question, regarding the TABLE object (I'm afraid I don't know a better term for it), if you look here: https://gist.github.com/dhoss/539650094085c2ef152acab6d5884a0d#file-baseservice-java-L24, you'll see I've got pseudo code attempting to try and fulfill a generic table object for the query. Normally, instead of TABLE, it would be a specific table object name generated by jooq, like GALLERY or IMAGE, in my case. I'm trying to determine what the appropriate generic would be in lieu of my pseudo code. I've dug into the generated table classes, and I've found this (apologies for the naming inconsistencies, I have some refactoring to do):public class Galleries extends TableImpl<GalleriesRecord> {private static final long serialVersionUID = 1035239683;/*** The reference instance of <code>public.galleries</code>*/public static final Galleries GALLERIES = new Galleries();/*** The class holding records for this type*/@Overridepublic Class<GalleriesRecord> getRecordType() {return GalleriesRecord.class;}// ....However, I attempted to make the table object generic several different types shown here, but none worked. I think I'll try your polymorphic parameter suggestion here as well, as it seems to make more sense the more I type, but I'd like your input if you have a better idea.
Then, a GalleriesService could be defined as such:class BaseService<R extends Record, T extends Table<R>> {T table();}
class GalleriesService extends BaseService<GalleriesRecord, Galleries> {}
--
You received this message because you are subscribed to a topic in the Google Groups "jOOQ User Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jooq-user/KUPyMa2581g/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jooq-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hi again Lukas,So, I've hit a bit of a wall. I'm not able to get the POJO type correct for my mapper method, which may not be a huge deal, since there's only one column/attribute that I need to mess with to make sure it contains a valid value, but making this "just work" would be a lot easier than refactoring that logic out somewhere else.This is the error I'm seeing:[ERROR] /home/devin/projects/lumos-gallery/gallery/src/main/java/com/lumos/service/ImageService.java:[32,8] com.lumos.service.ImageService is not abstract and does not override abstract method mapper() in com.lumos.service.BaseService[ERROR] /home/devin/projects/lumos-gallery/gallery/src/main/java/com/lumos/service/ImageService.java:[102,48] mapper() in com.lumos.service.ImageService cannot override mapper() in com.lumos.service.BaseService[ERROR] return type org.jooq.RecordMapper<com.lumos.db.tables.records.ImagesRecord,com.lumos.db.tables.pojos.Images> is not compatible with org.jooq.RecordMapper<org.jooq.Record,com.lumos.db.tables.pojos.Images>[ERROR] /home/devin/projects/lumos-gallery/gallery/src/main/java/com/lumos/service/ImageService.java:[101,3] method does not override or implement a method from a supertype[ERROR] /home/devin/projects/lumos-gallery/gallery/src/main/java/com/lumos/service/GalleryService.java:[29,8] com.lumos.service.GalleryService is not abstract and does not override abstract method mapper() in com.lumos.service.BaseService[ERROR] /home/devin/projects/lumos-gallery/gallery/src/main/java/com/lumos/service/GalleryService.java:[150,54] mapper() in com.lumos.service.GalleryService cannot override mapper() in com.lumos.service.BaseService[ERROR] return type org.jooq.RecordMapper<com.lumos.db.tables.records.GalleriesRecord,com.lumos.db.tables.pojos.Galleries> is not compatible with org.jooq.RecordMapper<org.jooq.Record,com.lumos.db.tables.pojos.Galleries>[ERROR] /home/devin/projects/lumos-gallery/gallery/src/main/java/com/lumos/service/GalleryService.java:[149,3] method does not override or implement a method from a supertypeHere's the pertinent code: https://gist.github.com/dhoss/09a3e3a074e975a91e9274a027b12d2c
3. I thought it might be easier to just extend the DAOImpl class like you suggested, but I'm still left with figuring out how to shoe-horn in sorting and such, so I don't think that's a viable route at this point.
I would, however, be more than happy to help contribute sorting and limiting conditions if that's on the future TODO list.
4. A slight tangent, but looking at my code I think it would be nicer to have an interface the lays out the CRUD contract, gets implemented in a CRUD base class, and then subclassed as needed. My hope would be to make my database CRUD a good deal more encapsulated and lighter weight, and allow me to have things like a cache service that's still a service but completely unrelated to the database CRUD operations. I'm probably just thinking out loud, but if that makes any of this simpler, please let me know your thoughts.
I am certainly not adverse to doing something else for my mapping code. I really just need to have the GALLERIES.COVER_PHOTO get set to either the value in the database or the default cover photo, which I suppose I could just set by default when inserting the record, so there's a value for that column in the database.
You have to decide whether you want to expose the jOOQ API to consumers of your services (e.g. Field, SortField, Condition, etc.) or if you want to implement your own criteria API. From then on it's just yak shaving.
Yes it is. I cannot seem to find the issue on GitHub right now, but it might be a nice feature. The only question is the same as the one above. Should we really expose the jOOQ API?
Thus far, caching has been out of scope for jOOQ, except perhaps for result set caching as displayed in this blog post:I'm always open for discussion though. What specific use-cases did you have in mind?
How about implementing that using either a trigger, or the DDL "DEFAULT" clause?If you want to implement that on the jOOQ layer, the RecordListener SPI might be interesting to you, given that you intend to implement a CRUD layer anyway.
--
You received this message because you are subscribed to a topic in the Google Groups "jOOQ User Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jooq-user/KUPyMa2581g/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jooq-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
To unsubscribe from this group and all its topics, send an email to jooq-user+unsubscribe@googlegroups.com.
--Devin Austin
https://www.stonecolddev.in
I think at this point it's going to be easiest to sort of lump common queries into service classes and use whatever available DAO methods get generated. I've had a lot of success in the past just dropping down closer to bare metal when features I want aren't immediately present in the current layer.
Yes it is. I cannot seem to find the issue on GitHub right now, but it might be a nice feature. The only question is the same as the one above. Should we really expose the jOOQ API?Please do let me know when/if you find it, and I'll be happy to fork and submit PRs. I think it would at least be nice to have the ability to either call something like .sort(COLUMN.asc()), or pass in a "configuration" object that potentially contains limit, order by and group by information, or pass in a parameter somehow. My background is mostly ruby/perl, so I don't know how this even translates to Java but something like this would be neat: .fetchAllBySlug(:order_by => 'created_on DESC'). I realize there's not a clean way to implement anonymous maps in Java, but it conveys my point, I think.
How about implementing that using either a trigger, or the DDL "DEFAULT" clause?If you want to implement that on the jOOQ layer, the RecordListener SPI might be interesting to you, given that you intend to implement a CRUD layer anyway.I dug through my code and I actually have the default getting set in my add() method. The problem I'm running into is still my mapper. Right after I submitted my question regarding the mapping error, I had actually implemented what you suggested for the generics, but it still doesn't like my method signature (up to date code: https://gist.github.com/dhoss/d40edcbfc111ad7604bc8ce0d3c9bdec):[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.2:compile (default-compile) on project gallery: Compilation failure[ERROR] /home/devin/projects/lumos-gallery/gallery/src/main/java/com/lumos/service/BaseService.java:[73,14] method map in interface org.jooq.Result<R> cannot be applied to given types;[ERROR] required: org.jooq.RecordMapper<? super org.jooq.Record,E>[ERROR] found: org.jooq.RecordMapper<R,P>[ERROR] reason: cannot infer type-variable(s) E[ERROR] (argument mismatch; org.jooq.RecordMapper<R,P> cannot be converted to org.jooq.RecordMapper<? super org.jooq.Record,E>)
sql.select().from(table())...fetch() // Type is Result<Record>
sql.selectFrom(table())...fetch() // Type is Result<R>
At this point, I just need something that will turn the objects I get back from jOOQ into my POJOs. It would be really neat if I could get the "implement your own damn mapper" per table/service working.
Previously, I had each table service passing a lambda to fetch() (pulled from here: https://github.com/lukaseder/minitwit/blob/master/src/main/java/com/minitwit/dao/MessageDao.java#L69), and that worked fine, but it doesn't lend itself very well to a base service that individual table service classes can inherit default CRUD methods from. I've been staring at this code for too long and am making things convoluted in my head, so forgive me if I'm making this whole thing too complicated, but making the record mapper piece generic enough, and implemented in the correct spot is what's confusing me the most. Looking through the docs, you can add one in your DSL context configuration (http://www.jooq.org/doc/3.7/manual/sql-execution/fetching/pojos-with-recordmapper-provider/), but that looks like it's still expecting a distinct class name to fetchInto(). You can also call .map() after .fetch() and pass it a record mapper (http://www.jooq.org/doc/3.7/manual/sql-execution/fetching/recordmapper/), which is what I'm trying to do, but running into the issue above. I'm certainly open to more intelligent approaches.By the way, I'm going to write up a tutorial on all this once it gets sorted out and I'm more than happy to contribute documentation if it fits in anywhere.
To unsubscribe from this group and all its topics, send an email to jooq-user+...@googlegroups.com.
--Devin Austin
https://www.stonecolddev.in
--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
I agree, explicit class literals would be much nicer, but I'm not able to picture how that gets passed around. Do you have an example to share?
Now that you put it that way re: "why use daos when it gets redefined substantially anyway," then yea it doesn't make much sense. I actually am only using the Dao methods in one or two spots and that's out of pure laziness. If one wants a DSL for Dao querying, then it makes sense for them to build it themselves. I think it takes things in too far off in a different direction than what jOOQ aims to initially provide trying to support it.
I've responded to your other email, and after I meditate on your response for a bit, I'll draft up an article and post it with your blessing, and you can obviously link to it.
Thanks again!
--
I agree, explicit class literals would be much nicer, but I'm not able to picture how that gets passed around. Do you have an example to share?
BaseService(Class<R> recordType, Class<P> pojoType) {...}
Now that you put it that way re: "why use daos when it gets redefined substantially anyway," then yea it doesn't make much sense. I actually am only using the Dao methods in one or two spots and that's out of pure laziness. If one wants a DSL for Dao querying, then it makes sense for them to build it themselves. I think it takes things in too far off in a different direction than what jOOQ aims to initially provide trying to support it.
I've responded to your other email, and after I meditate on your response for a bit, I'll draft up an article and post it with your blessing, and you can obviously link to it.