Spring3+mybatis3 generic dao(or mapper) - mybatis

I have integrated spring3 + mybatis3,and it worked good.
Then I found that many SQLs will be written like this:
select * from table1 where id=#{id}
select * from table2 where id=#{id}
We don't need repeat as a programmer!
So,Can we defined a genric dao or mapper to avoid this repeat? Provide a demo is better.
Some links can help is kindly too.
It bothers me for a long time,need a hand.
I want to write my code like this:
Test.java:
just a enity.
TestMapper.java:
public interface TestMapper extends GenericMapper {
public void testMethod1(String..);
//other methods here
}
GenericMapper.java:
public interface GenericMapper<T, PK> {
public T select(PK id);
public boolean update(T t);
public boolean delete(PK id);
public boolean insert(T t);
}
defind bean in spring-xx.xml:
<bean id="testMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
<property name="mapperInterface" value="com.jackson.mapper.TestMapper" />
</bean>
Call in my service layer like this:
// Please**NOTICE**:method select is defined in GenericMapper.
TestService.java:
public TestMapper testMapper;
public Test get(Integer id) {
Test test = testMapper.select(id);
doSmth(test);
}
Just a few minutes ago,Someone said we can use a Interceptor interface. And I am trying now.
Thanks!
--jackson

One of the options is to use mybatis-generator.

http://classnotfound.net/blog/mybatisspringgenerics/
I think this tutorial has exactly what you are looking for. I am not sure what version of Java (or editor config) he is running but I had to add on the Dao methods and suppress the unchecked castings (T) and raw types warnings to get it work on eclipse mars 2 using java 8.

I know I might be late but this library from google will address your issue. I have been using it in over 10 projects.

Related

Injecting all mappers in a list and calling a convert method polymorphically

Is there a way to autowire all mappers written with Mapstruct in Spring just like we used to do with the Spring Converter interface and calling one toEntity(or convert or any other name)? In spring, it is easy because they all implement the same functional interface and by making it inherit from another interface we can determine the right converter in the runtime like below:
import org.springframework.core.convert.converter.Converter;
public interface CustomConverter<S extends ..., T extends ...> extends Covnerter<S,T>{
boolean supports(Class clazz);
}
And then injecting it would be easy:
#Autowire
private final List<CustomConverter> myConverters;
and by calling supports we would determine the right kind of converter and then call convert against it.
I had something like this in mind:
#Mapper
public interface MyMapper extends CustomMapper<MyEntity, MyDto>{
MyMapper INSTANCE = Mappers.getMapper(MyMapper.class);
MyEntity toEntity(MyDto dto);
default boolean supports(Class clazz) {
return MyDto.class.isAssignableFrom(clazz);
}
And
public interface CustomMapper<T extends ..., S extends ...> {
boolean supports(Class clazz);
T toEntity(S dto);
}
This does not work though.
Do you have any suggestions here? I might have misunderstood this all together...Thanks.
Checkout: https://github.com/mapstruct/mapstruct-spring-extensions
The author made and adapter based on a discusion in this SO issue.
A non spring based solution can be found here. Although you need to write your own annotation processor.

get list of services implementations with OSGi declarative services

I have a very simple example of declarative services. I'm following this tutorial http://www.eclipsezone.com/eclipse/forums/t97690.html?start=0. Every thing is working as expected. However, I cannot figure out how I can make the "SampleImporter" (which is the bundle that is expected to use other bundles' services) aware of the list of "SampleExporter" (bundle providing a service). In other words, I want the "SamlpeImporter" to see the ID of the bundle(s) that it is eventually using. This information is very useful for my application.
here is the XML file for SampleExporter:
<?xml version="1.0"?>
<component name="samplerunnable">
<implementation class="org.example.ds.SampleRunnable"/>
<property name="ID" value="expoter" />
<service>
<provide interface="java.lang.Runnable"/>
</service>
while for the SampleImporter:
<?xml version="1.0"?>
<component name="commandprovider1">
<implementation class="org.example.ds.SampleCommandProvider1"/>
<service>
<provide interface="org.eclipse.osgi.framework.console.CommandProvider"/>
</service>
<reference name="RUNNABLE"
interface="java.lang.Runnable"
bind="setRunnable"
unbind="unsetRunnable"
cardinality="0..1"
policy="dynamic"/>
</component>
In the Importer side, I have the following function:
public class SampleCommandProvider1 implements CommandProvider {
private Runnable runnable;
public synchronized void setRunnable(Runnable r) {
runnable = r;
}
public synchronized void unsetRunnable(Runnable r) {
runnable = null;
}
public synchronized void _run(CommandInterpreter ci) {
if(runnable != null) {
runnable.run();
} else {
ci.println("Error, no Runnable available");
}
}
public String getHelp() {
return "\trun - execute a Runnable service";
}
}
This works fine but then if I want to get the value of the property, using
public synchronized void setRunnable(Runnable r, Map properties)
or
public synchronized void setRunnable(Runnable r, ServiceReference reference)
the method run of the exporter is never called which means that the bind function (setRunnable is not called).Hwever, using the console command "services" I see that the exporter bundle is used by the imporeter one. Also, using ss and ls I can see that the component eporter is "satisfied".
What is wrong with my implementetion?
Thanks in advance
Cheers
Marie
The following bind signature is not supported by any version of DS:
public void setRunnable(Runnable r, ServiceReference ref)
Instead you will have to take only the ServiceReference and use either the ComponentContext or BundleContext to access the service instance object.
Alternatively if you want a more POJO-style way of accessing service properties, the following bind signature is allowed in DS 1.1 (but not in DS 1.0):
public void setRunnable(Runnable r, Map properties)
To access DS 1.1 features, you need to add the correct namespace to your XML as follows:
<component xmlns='http://www.osgi.org/xmlns/scr/v1.1.0' name='...'>
By the way, I wrote this original article a very long time ago! These days I would use bnd annotations to avoid having to write the XML document by hand.

How to make JPA EntityListeners validate the existence of an interface

I am working in J2EE 5 using JPA, I have a working solution but I'm looking to clean up the structure.
I am using EntityListeners on some of the JPA objects I am persisting, the listeners are fairly generic but depend on the beans implementing an interface, this works great if you remember to add the interface.
I have not been able to determine a way to tie the EntityListener and the Interface together so that I would get an exception that lead in the right direction, or even better a compile time error.
#Entity
#EntityListener({CreateByListener.class})
public class Note implements CreatorInterface{
private String message;....
private String creator;
....
}
public interface CreatorInterface{
public void setCreator(String creator);
}
public class CreateByListener {
#PrePersist
public void dataPersist(CreatorInterface data){
SUser user = LoginModule.getUser();
data.setCreator(user.getName());
}
}
This functions exactly the way I want it to, except when a new class is created and it uses the CreateByListener but does not implement the CreatorInterface.
When this happens a class cast exception is thrown somewhere deep from within the JPA engine and only if I happen to remember this symptom can I figure out what went wrong.
I have not been able to figure a way to require the interface or test for the presence of the interface before the listener would be fired.
Any ideas would be appreciated.
#PrePersist
public void dataPersist(Object data){
if (!(data instanceof CreatorInterface)) {
throw new IllegalArgumentException("The class "
+ data.getClass()
+ " should implement CreatorInterface");
}
CreatorInterface creatorInterface = (CreatorInterface) data;
SUser user = LoginModule.getUser();
creatorInterface.setCreator(user.getName());
}
This does basically the same thing as what you're doing, but at least you'll have a more readable error message indicating what's wrong, instead of the ClassCastException.

How to access the method which is defined by the super interface in JSF?

I've tried to learn the JSF 2.0 by implementing the managed bean via the NetBeans 7. By overview it contains the property as a data object which implements the interface as the following: -
public interface MyInterface1 {
void setName(String name);
String getName();
}
public interface MyInterface2 extends MyInterface1 {
void setPhone(String phone);
String getPhone();
}
public class MyInfo implements MyInterface2 {
//...Getter, Setter
}
#ManagedBean(name="myBean")
public class MyManagedBean {
private MyInfo myInfo = new MyInfo();
//..Getter, Setter
}
When I enter the EL at the JSF/XHTML as
#{myBean.myInfo....}
the methods which are defined at the Super Interface, the MyInterface1 is not displayed.
I'm not sure if it is a tool limitation or I may do something wrong or not.
Could you please help to advise further? Thank you very much for your help in advance. I'm looking forward to hearing from you soon.
Regards,
Charlee Ch.
This is definitely a limitation of the Netbeans editor. I've constantly struggled with similar issues in NB 6.9, code completion would sometimes not work at all, sometimes missing out interfaces/methods, etc. But hey, you can go ahead and type in the method name yourself - it should work.

Generic repository implementation with EF

For a simple repository
public interface ISimpleRepository<T>
{
IApplicationState AppState { get; set; }
void Add(T instance);
void Delete(T instance);
void Delete(Guid rowGuid);
IQueryable<T> GetAll();
T Load(Guid rowGuid);
void SaveChanges();
void Update(T instance);
}
my implementation of the Load() method for specific repository for class Product might look like this:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
Now this is assumed when my repository implementation class looks like this:
public class EntityFrameworkProductsProvider : IRepository<Product> ...
What if I had like dozens or hundreds of this small and simple entities that would all use the same behaviour when doing CRUDs (use the same implementation of methods)? I certainly don't want to go and create a class to implement IRepository for each one of them..
I want something like this:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
but I don't know how to implement the LINQ Select expression then because of course I can't write from e in _ctx.T where e... or do I?
I haven't run into this scenario yet because so far I only had very specific entities with custom repository implementation.
Because you tagged your question with entity-framework and entity-framework-4 I assume you are using ObjectContext API. ObjectContext offers method CreateObjectSet<T> which is equivalent of Set<T> on DbContext.
This question is actually duplicate of either:
Generic GetById with DbContext
Generic GetById with ObjectContext
Instead of writing _ctx.Products, you can write _ctx.Set<T>. That takes care of half of the problem (you need to add a generic constraint where T: class to your repository)
Then, if rowid is the object's key, you can use _ctx.Set<T>.Find(rowid) instead of a LINQ query to retrieve by Id.
Alternatively, you can create a base interface IHaveId (or a BaseEntity class, whatever you like) which has the Id property, and then add that as an generic constraint on T, so you can use it in your queries.
If you're using EF 4.1, see the sample generic repository here:
http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
I know that this is possible in EF4.1 with the DbContext API, where you have a "Set" method on the context that gets you the entity set corresponding to the type T. this way, you could have your repository like this:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
one more remark: I think you could use this syntax :
return _ctx.Products.FirstOrDefault(c=>c.id == rowid);
to get the entity you want instead of using the (from... in...). it's clearer (in my opinion) :)
Hope this helps