https://github.com/rickcr/mybatis-generic-crud
Many times your application consists of doing common CRUD type operations (Create, Read, Update, Delete.)
I'm a big fan of MyBatis and a few solutions have been proposed to handle some of the basic CRUD in a generic fashion. This is just one 'partially generic' way to handle these common things. I say 'partially' since I've seen other approaches, such as having a single mapper and you pass in the table name and a list of columns etc. That approach is decent as well, but I've found that many times you start out generic but you'll often have to tweak a few things such that your CRUD becomes a bit more complicated. Following the approach below you have the flexibility to override whatever you want.
The drawback (minor) is that, yes, you still need to create a place-holder mapper interface and you still need to create your mapper xml file and the corresponding CRUD sql in it.
The benefit is that if you follow the convention of naming the mapper methods to match the GenericCrudMapper, you typically are only writing the SQL, and the Java side becomes simple.
Note, I also created a GenericCrudService class. If you follow any of my other tutorials you'll realize that I do prefer to have my Mappers used within a service class. This is just my preference and not required. I've found in the 'real world' that I often need to do more stuff around my basic CRUD operations so that using the Mapper within a Service class gives me an extra layer to shield the client - typically the UI - from having to handle the other needed business logic around the CRUD operations.
Showing posts with label java. Show all posts
Showing posts with label java. Show all posts
Wednesday, June 10, 2015
Friday, April 10, 2015
MyBatis-Spring-ZK Maven Multimodule Project
I know have a sample project that uses MyBatis, Spring, and ZK, broken out into separate Maven modules. It's a more realistic setup for how you'd typically organize your 'real life' projects, especially in a corporate environment. Domain module (pojos), Services module (MyBatis), Web project (ZK)
Friday, May 31, 2013
ZK - Paginating Large Results sets in ZK with MyBatis
Benefit of this type of paging is that it doesn't load all the results up front. Useful for very large result sets. I'm a fan of MyBatis, so this example below demonstrates the use with MyBatis.
ZUL
<paging id="executionsPaging" onCreate="executionsList.setPaginal(self)" totalSize="@bind(vm.executionsTotalSize)" pageSize="@bind(vm.executionsPageSize)" activePage="@bind(vm.currentPageNumber)" onPaging="@command('pageExecutions', pageNum=event.activePage)" /> <listbox id="executionsList" model="@load(vm.executions)" selectedItem="@bind(vm.selectedExecution)".... />
Executions ViewModel
public class ExecutionsVM { private final static Logger logger = LoggerFactory.getLogger(ExecutionsVM.class); private Listexecutions = new ArrayList (); private ExecutionSearchFilter searchFilter = new ExecutionSearchFilter(); private long executionsTotalSize = 0l; private int executionsPageSize = 25; private int currentPageNumber = 0; @WireVariable private ExecutionService executionService; @NotifyChange({"executions","executionsTotalSize"}) @Command public void pageExecutions(@BindingParam("pageNum") int pageNum) { logger.debug("pageExecutions for pagNum {}", pageNum); this.currentPageNumber = pageNum; populateSearchFilter(); executions = executionService.getExecutions(searchFilter); executionsTotalSize = executionService.getExecutionsSize(searchFilter); } private void populateSearchFilter() { int base = this.currentPageNumber * executionsPageSize; int firstRow = base + 1; int lastRow = base + executionsPageSize; searchFilter.setLowerRowLimit(firstRow); searchFilter.setUpperRowLimit(lastRow); } }
Executions Service (wraps Mapper)
@Service public class ExecutionService { @Resource private ExecutionMapper executionMapper; public ListfeatchExecutions(ExecutionSearchFilter searchFilter) { return executionMapper.getExecutions(searchFilter); } }
Executions Mapper
public interface ExecutionMapper { ListfeatchExecutions(ExecutionSearchFilter searchFilter) }
Search Filter POJO
public class ExecutionSearchFilter { private int upperRowLimit; private int lowerRowLimit; //setters/getters }
Executions Mapper MXL
<select id="getExecutions" resultMap="executionResultMap" parameterType="ExecutionSearchFilter"> select EXECUTION_ID, EXECUTION_NM, ROW_NUM FROM ( SELECT tempRow.EXECUTION_ID, tempRow.EXECUTION_NM, rownum ROW_NUM from ( SELECT e.EXECUTION_ID, e.EXECUTION_NM FROM EXECUTION_T e ) tempRow WHERE rownum <![CDATA[ <= ]]> #{upperRowLimit} ) WHERE ROW_NUM >= #{lowerRowLimit} </select>
Friday, May 24, 2013
ZK Tips
Figured I'd list some of the tips here as I work with ZK. A lot of things aren't immediately apparent even using the online docs.
In annoying thing in ZK is that if your ViewModel extends another ViewModel and your base ViewModel decides that it needs to delegate a call to its subclass, the subclass @NotifyChange({"props}") will not automatically be triggered. As an example take:
Most of the documentation and examples demonstrate declaring GlobalCommmand annotations like:
NotifyChange from your Base ViewModels
In annoying thing in ZK is that if your ViewModel extends another ViewModel and your base ViewModel decides that it needs to delegate a call to its subclass, the subclass @NotifyChange({"props}") will not automatically be triggered. As an example take:
public abstract class BaseVM { public void doSomething() { //do Stuff //delegate to implementing class doSomeStuff(); } public abstract void doSomeStuff(); } public ChildVM extends BaseVM { private String someProperty; @NotifyChange("someProperty") public void doSomeStuff() { someProperty = "blah"; } public String getSomeProperty() { return someProperty; } }It would be nice if when "doSomeStuff" is called that "someProperty" would be able to be notified so it could display properly in your zul. Matze2 on the forums helped provide the work around http://forum.zkoss.org/question/86637/notifychange-in-subclass-methods-called-from-parent-will-not-fire/ Solution is to use the "Binder" object. Illustrated as so...
public abstract class BaseVM { protected Binder binder; @Init public final void init(@ContextParam(ContextType.BINDER) Binder _binder) { binder = _binder; } public void doSomething() { //do Stuff //delegate to implementing class doSomeStuff(); binder.notifyChange(this, "someProperty"); } public abstract void doSomeStuff(); } public ChildVM extends BaseVM { private String someProperty; @Init(superclass=true) public void init() { } @NotifyChange("someProperty") public void doSomeStuff() { someProperty = "blah"; } public String getSomeProperty() { return someProperty; } }Don't forget the @Init(superclass=true) in your subclass (I think you can add it to the Class annotation if you aren't providing an init method in your subclass.) The above is clunky but it works.
Use Constants for your GlobalCommands
Most of the documentation and examples demonstrate declaring GlobalCommmand annotations like:
@GlobalCommand public void someMethod() { ... }and calling it from some other ViewModel like so:
BindUtils.postGlobalCommand(null, null, "someMethod", null);The problem with this is it's extremely fragile. If you decide to refactor your method name, you end up then having to do a search and replace for everywhere you've called your Global command with "someMethod." Possibly more annoying is you do not get any IDE help when you want to post to this GlobalCommand from another ViewModel... you need to recall the exact name of the method and if you can't recall the name you have to remember where that GlobalCommand was defined which could take time in a large project. Instead, I recommend always getting in the habit of using a GlobalCommandValues class that declares the GlobalCommand as String constant and then using it in your annotation and of course in your postGlobalCommand calls. This seems obvious, but I wasn't even aware it was an option.
//GlobalCommandValues class public static final String SOME_METHOD = "someMethod"; //ViewModel @GlobalCommand(GlobalCommandValues.SOME_METHOD) public void someMethodDoesntHaveToMatchYourConstant() { ... } //Usage BindUtils.postGlobalCommand(null, null, GlobalCommandValues.SOME_METHOD, null);
Sunday, May 3, 2009
Set pojo properties with groovy sql row results
This is probably documented somewhere that you can do this with a Map and a regular typed Object, I just hadn't run across it and tried it to see what happens.
You can just pass in a Map of properties to an Object and as long as you don't have any properties in your Map that are not defined in the class, it'll work fine. As an example:
This comes in real handy when want you want to populate some groovy sql results into a collection of typed objects. As an example:
You can just pass in a Map of properties to an Object and as long as you don't have any properties in your Map that are not defined in the class, it'll work fine. As an example:
class Person {
String name
Integer age
String address
}
def map = [ name: "Joe", age: 4, address: "Somewhere"]
Person p = new Person(map)
println "Peson name: $p.name, address: $p.address"
This comes in real handy when want you want to populate some groovy sql results into a collection of typed objects. As an example:
def getPersons() {
def persons = []
sql.eachRow("Select * from Person") {
persons << new Person( it.toRowResult() )
}
return persons
}
Monday, April 6, 2009
Using Groovy @Delegate
Groovy 1.6 introduces some killer stuff!
I really like @Delegate.
For those that don't use Groovy much, what @Delegate does is best seen by an example. The one in the link above is pretty good dealing with Date in an Event, but as a real world example here's how I needed it....
groovy.sql is pretty cool and you can call toRowResult() on each groovy result set object, which lets you use those GroovyRowResult objects directly calling the column name as properties... for example..
Ok simple enough, but now what if you wanted to also get a "fullName" property? Ok simple enough we'll just make a Person object and create a method to create it. But wait, I still need access to all those other database fields. Now sure in many CRUD apps you'd already have a Person object with all the typical fields firstName, lastName etc... but in this case I only need display data and I'm perfectly happy with using the database field names for the property names so I want to just use my groovyRowResult directly but also want to be able to call "lastNam.". So in Java what would one do? I don't want to mess around trying to extend GroovyRowResult (if I even could?) or maybe my Person also needed to already extend another Base object as it is. Obviously you want to wrap row in an adapter and then in Java you'd have to use some reflection and proxy method/property calls to the wrapped row object if a call to a method/property wasn't found in Person. Sort of a pain to have to code that proxy stuff though. Granted not difficult and you can cut and paste it from other projects once you've done it once, but with Groovy it's even easier and much cleaner. for my sql example above...
Before using Delegate I was using propertyMissing, which would be fine in this case since I only have one delegate but things would be trickier if I had multiple nested objects (whereas using @Delegate it wouldn't be an issue - assuming you didn't have conflicting method/property names - in which case not sure what would happen.) Even using the old propertMissing in Groovy is quite cool:
I really like @Delegate.
For those that don't use Groovy much, what @Delegate does is best seen by an example. The one in the link above is pretty good dealing with Date in an Event, but as a real world example here's how I needed it....
groovy.sql is pretty cool and you can call toRowResult() on each groovy result set object, which lets you use those GroovyRowResult objects directly calling the column name as properties... for example..
def sql = Sql.newInstance("jdbc:jtds:sybase://.....I", "user", "passr", "net.sourceforge.jtds.jdbc.Driver")
def results = []
sql.eachRow("SELECT firstName, lastName FROM Person") {
results << it.toRowResult()
}
//print first and last names from results collected:
results.each {
println "firstName = $it.firstName lastName= $it.lastName"
}
Ok simple enough, but now what if you wanted to also get a "fullName" property? Ok simple enough we'll just make a Person object and create a method to create it. But wait, I still need access to all those other database fields. Now sure in many CRUD apps you'd already have a Person object with all the typical fields firstName, lastName etc... but in this case I only need display data and I'm perfectly happy with using the database field names for the property names so I want to just use my groovyRowResult directly but also want to be able to call "lastNam.". So in Java what would one do? I don't want to mess around trying to extend GroovyRowResult (if I even could?) or maybe my Person also needed to already extend another Base object as it is. Obviously you want to wrap row in an adapter and then in Java you'd have to use some reflection and proxy method/property calls to the wrapped row object if a call to a method/property wasn't found in Person. Sort of a pain to have to code that proxy stuff though. Granted not difficult and you can cut and paste it from other projects once you've done it once, but with Groovy it's even easier and much cleaner. for my sql example above...
class Person {
@Delegate(interfaces=false) GroovyRowResult row
def getFullName() {
return "${row.firstName} ${row.lastName}"
}
}
//...
sql.eachRow("SELECT firstName, lastName FROM Person") {
results << new Person( row: it.toRowResult() )
}
results.each {
println "firstName = $it.firstName" // finds firstName in delegate!!!!
println "lastName = $it.lastName"
}
Before using Delegate I was using propertyMissing, which would be fine in this case since I only have one delegate but things would be trickier if I had multiple nested objects (whereas using @Delegate it wouldn't be an issue - assuming you didn't have conflicting method/property names - in which case not sure what would happen.) Even using the old propertMissing in Groovy is quite cool:
//using propertyMissing
class Person {
@Delegate GroovyRowResult row
def getFullName() {
return "${row.firstName} ${row.lastName}"
}
def propertyMissing(String prop) {
def result = row."${prop}"
}
}
Wednesday, March 4, 2009
Maven2-Groovy-JUnit-Guice
Here's how I'm currently setting up my testing with groovy and maven, using Guice and JUnit. (I had trouble getting this all to work with TestNG, which is my preferred testing framework, so if someone gets it all working, please let me know.)
I'm usting AtUnit to help out with the Guice/JUnit integration. It makes things very simple.
In your pom.xml build plugins section:
My groovy tests are located in src/test/groovy (Using Eclipse I then mark this as a source folder also so it's easier to use in a flattened package structure.)
When you look at the AtUnit examples, you'll see several ways to set things up. I like to use my existing Guice module class that I've already created, so I start out with a TestBase class that my tests will extend...
If you don't want to use a Module, you can just do all your binding right in the configure method above and everything will work just fine (and this is the way they demonstrate on the AtUnit site example.)
Now one of my groovy tests:
mvn clean install and that's it.
I'm usting AtUnit to help out with the Guice/JUnit integration. It makes things very simple.
In your pom.xml build plugins section:
<plugin>
<groupid>org.codehaus.groovy.maven</groupid>
<artifactid>gmaven-plugin</artifactid>
<version>1.0-rc-4</version>
<executions>
<execution>
<goals>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
My groovy tests are located in src/test/groovy (Using Eclipse I then mark this as a source folder also so it's easier to use in a flattened package structure.)
When you look at the AtUnit examples, you'll see several ways to set things up. I like to use my existing Guice module class that I've already created, so I start out with a TestBase class that my tests will extend...
public class TestBase implements Module {
public void configure(Binder binder) {
binder.install(new MyGuiceModule());
}
}
If you don't want to use a Module, you can just do all your binding right in the configure method above and everything will work just fine (and this is the way they demonstrate on the AtUnit site example.)
Now one of my groovy tests:
@RunWith(AtUnit.class)
@Container(Container.Option.GUICE)
public class ExecutionLogTest extends TestBase {
@Inject @Unit ExecutionLogs execLogs;
@Test
public void testExeuctionLogs() {
println "testExeuctionLogs"
//... execLogs.find(... )
}
}
mvn clean install and that's it.
Subscribe to:
Posts
(
Atom
)