首先我们在调用Mapper的相关方法时实现动态代理,将相关参数封装好,这样我们调用的方法时实际上我们将所有的方法调用都封装了起来。外部只需要调用一个接口即可。下面的代码有很多缺点,仅作参考
@Data
public class Blog {
private String id;
private String name;
}
public interface BlogMapper {
Blog queryBlog(int id);
}
public class TestMain {
public static void main(String[] args) {
MySqlSession mySqlSession = new MySqlSession();
BlogMapper blogMapper = mySqlSession.getMapper(BlogMapper.class);
Blog blog = blogMapper.queryBlog(1);
System.out.println(blog);
}
}
public class MySqlSession {
private MyConfiguration myConfiguration = new MyConfiguration();
public <T> T select(String sql, String param){
ConfigXmlMsg configXmlMsg = ConfigXmlMsg.getConfigXmlMsg();
try {
Class.forName(configXmlMsg.getDriverClassName());
Connection con = DriverManager.getConnection(configXmlMsg.getUrl()
,configXmlMsg.getUsername()
,configXmlMsg.getPassword());
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(new MyConfiguration().getMapperMsg().getSql()+param);
System.out.println("执行的语句是:"+new MyConfiguration().getMapperMsg().getSql()+param);
Blog blog = new Blog();
while (rs.next()){
blog.setId(rs.getString(1));
System.out.println("id结果:"+blog.getId());
blog.setName(rs.getString(2));
System.out.println("name结果:"+blog.getName());
}
return (T)blog;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//<T> T表示返回的类型由调用者决定
//这里实际上交给MyMapperProxy先处理
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> clas){
//动态代理调用
return (T) Proxy.newProxyInstance(clas.getClassLoader(),new Class[]{clas},
new MyMapperProxy(myConfiguration,this));
}
}
public class MyMapperProxy implements InvocationHandler{
//这里没有使用xml而是使用两个实体类代替
private MySqlSession mySqlsession;
private MyConfiguration myConfiguration;
public MyMapperProxy(MyConfiguration myConfiguration, MySqlSession mySqlsession) {
this.myConfiguration=myConfiguration;
this.mySqlsession=mySqlsession;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MapperXmlMsg mapperXmlMsg = myConfiguration.getMapperMsg();
//先验证我们的mapper.xml文件中有没有调用的接口类,这里只用了一个mapper举例
if(!method.getDeclaringClass().getName().equals(mapperXmlMsg.getInterFaceName())){
return null;
}
Object object = null;
//xml中是否有对应的方法
if(method.getName().equals(mapperXmlMsg.getFunctionName())){
object = mySqlsession.select(mapperXmlMsg.getSql(),String.valueOf(args[0]));
}
return object;
}
}
public class MyConfiguration {
@SuppressWarnings("rawtypes")
public MapperXmlMsg getMapperMsg(){
//实际应该读取xml并封装为一个对象,这里为了理解直接用写好的类代替
MapperXmlMsg mapperXmlMsg = new MapperXmlMsg();
//对应namespace
mapperXmlMsg.setInterFaceName("com.mapper.BlogMapper");
//对应id
mapperXmlMsg.setFunctionName("queryBlog");
mapperXmlMsg.setSql("select * from blog where id = ");
return mapperXmlMsg;
}
}
@Data
public class MapperXmlMsg {
//真实情况应该使用DOM4j解析后封装
private String InterFaceName;
private String FunctionName;
private String Sql;
}
@Data
public class ConfigXmlMsg {
private String driverClassName;
private String url;
private String username;
private String password;
public static ConfigXmlMsg getConfigXmlMsg(){
ConfigXmlMsg configXmlMsg = new ConfigXmlMsg();
configXmlMsg.setDriverClassName("com.mysql.jdbc.Driver");
configXmlMsg.setUrl("jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8");
configXmlMsg.setPassword("root");
configXmlMsg.setUsername("root");
return configXmlMsg;
}
}
运行测试类结果如下:
执行的语句是:select * from blog where id = 1
id结果:1
name结果:dfgdfg
Blog(id=1, name=dfgdfg)
这仅仅是一个参考,具体详情还要根据mybatis源码分析。