由于业务关系 巴拉巴拉巴拉
好吧 简单来说就是
原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能
现在想要达到效果是 只通过一个方法就可以实现 也就是功能合并 所以就有了下面的实践
既然是基于MyBatis 所以就先搭建一个Mybatis的小项目
1.01导入 mybatis和mysql的包
1.02.配置文件 Configuration.xml 中添加
1
2
3
4
5
6
7
8
9
10
11
|
< environments default = "development" >
< environment id = "development" >
< transactionManager type = "JDBC" />
< dataSource type = "POOLED" >
< property name = "driver" value = "com.mysql.jdbc.Driver" />
< property name = "url" value = "jdbc:mysql://localhost:3306/test" />
< property name = "username" value = "root" />
< property name = "password" value = "" />
</ dataSource >
</ environment >
</ environments >
|
2.01.然后创建一个模块user 创建user表
1
2
3
4
5
6
7
8
9
|
DROP TABLE IF EXISTS ` user `;
CREATE TABLE ` user ` (
`id` int (11) NOT NULL AUTO_INCREMENT,
` name ` char (32) NOT NULL ,
`t1` char (32) DEFAULT NULL ,
`t2` char (32) DEFAULT NULL ,
`t3` char (32) DEFAULT NULL ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
|
3.01.写对应bean:User.java
1
2
3
4
5
6
7
8
9
10
11
12
|
package lqb.bean;
public class User extends Common{
private String id;
private String name;
private String t1;
private String t2;
private String t3;
//省略get set
}
|
3.02.对应的mapper: UserMapper.java和UserMapper.xml
简单实现下CRUD
1
2
3
4
5
6
7
8
|
public interface UserMapper {
public User selectByID( int id);
public List<User> select();
public int insert(User u);
public int update(User u);
public int delete(User u);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
< mapper namespace = "lqb.mapper.UserMapper" >
< select id = "selectByID" parameterType = "int" resultType = "lqb.bean.User" >
select * from `user` where id = #{id}
</ select >
< select id = "select" resultType = "lqb.bean.User" parameterType = "lqb.bean.User" >
select * from `user`
</ select >
< insert id = "insert" parameterType = "lqb.bean.User" >
insert into user (id,name,t1,t2,t3) values (#{id},#{name},#{t1},#{t2},#{t3})
</ insert >
< update id = "update" parameterType = "lqb.bean.User" >
update user set name=#{name},t1=#{t1},t2=#{t2},t3=#{t3} where id=#{id}
</ update >
< delete id = "delete" parameterType = "lqb.bean.User" >
delete from user where id=#{id}
</ delete >
</ mapper >
|
3.03.然后 在配置文件Configuration.xml中添加user的配置
1
2
3
|
< mappers >
< mapper resource = "lqb/mapper/UserMapper.xml" />
</ mappers >
|
3.04.然后是实现:UserService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class UserService {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
static {
try {
reader = Resources.getResourceAsReader( "Configuration.xml" );
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e){
e.printStackTrace();
}
}
public static SqlSessionFactory getSession(){
return sqlSessionFactory;
}
}
|
4.01 好 然后是重点了
思路: 截获查询的sql 然后拼成 sqlPage和sqlCount 再进行查找取值 然后赋传入对象
所以我们就需要创建一个基础类来让user.java来继承
1
2
3
4
5
6
7
|
public class Common {
private int pagesize;
private int pageid;
private int pagebegin;
private int count;
//省略 get set
}
|
4.02 然后 让User继承Common
1
|
public class User extends Common{
|
4.03 那怎么截获sql呢 我们就要写一个mybatis的拦截器 用来拦截sql请求 PageInterceptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Intercepts ({
@Signature (type = StatementHandler. class , method = "prepare" , args = {Connection. class }),
@Signature (type = ResultSetHandler. class , method = "handleResultSets" , args = {Statement. class })
})
public class PageInterceptor implements Interceptor {
//插件运行的代码,它将代替原有的方法
@Override
public Object intercept(Invocation invocation) throws Throwable {
}
// 拦截类型StatementHandler
@Override
public Object plugin(Object target) {
}
@Override
public void setProperties(Properties properties) {
}
|
4.04 首先 设置拦截类型 重写plugin方法
1
2
3
4
5
6
7
8
|
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this );
} else {
return target;
}
}
|
4.05 然后 就要重写最重要的intercept了
这里我们有一个设定 如果查询方法含有searchpage 就进行分页 其他方法无视
所以就要获取方法名
1
2
3
4
|
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement=(MappedStatement) metaStatementHandler.getValue( "delegate.mappedStatement" );
String selectId=mappedStatement.getId();
|
4.06 然后判断下 如果含有searchpage 就获取sql
1
2
3
4
|
BoundSql boundSql = (BoundSql) metaStatementHandler.getValue( "delegate.boundSql" );
// 分页参数作为参数对象parameterObject的一个属性
String sql = boundSql.getSql();
Common co=(Common)(boundSql.getParameterObject());
|
4.07 然后 根据这个sql 重新拼写countsql和pagesql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
String countSql=concatCountSql(sql);
String pageSql=concatPageSql(sql,co);
...
public String concatCountSql(String sql){
StringBuffer sb= new StringBuffer( "select count(*) from " );
sql=sql.toLowerCase();
if (sql.lastIndexOf( "order" )>sql.lastIndexOf( ")" )){
sb.append(sql.substring(sql.indexOf( "from" )+ 4 , sql.lastIndexOf( "order" )));
} else {
sb.append(sql.substring(sql.indexOf( "from" )+ 4 ));
}
return sb.toString();
}
public String concatPageSql(String sql,Common co){
StringBuffer sb= new StringBuffer();
sb.append(sql);
sb.append( " limit " ).append(co.getPagebegin()).append( " , " ).append(co.getPagesize());
return sb.toString();
}
|
4.08 然后 通过jdbc查询count 然后把值绑定给common
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
Connection connection = (Connection) invocation.getArgs()[ 0 ];
PreparedStatement countStmt = null ;
ResultSet rs = null ;
int totalCount = 0 ;
try {
countStmt = connection.prepareStatement(countSql);
rs = countStmt.executeQuery();
if (rs.next()) {
totalCount = rs.getInt( 1 );
}
} catch (SQLException e) {
System.out.println( "Ignore this exception" +e);
} finally {
try {
rs.close();
countStmt.close();
} catch (SQLException e) {
System.out.println( "Ignore this exception" + e);
}
}
//绑定count
co.setCount(totalCount);
|
4.09 再把pagesql赋给元BoundSql
1
|
metaStatementHandler.setValue( "delegate.boundSql.sql" , pageSql);
|
4.10 最后在配置文件中添加拦截器配置
1
2
3
|
< plugins >
< plugin interceptor = "lqb.interceptor.PageInterceptor" />
</ plugins >
|
4.11 好然后 在UserMapper.java和UserMapper.xml中添加分页代码
1
2
3
|
< select id = "selectPage" parameterType = "lqb.bean.User" resultType = "lqb.bean.User" >
select * from `user` where id in(3,4,6,8) order by id
</ select >
|
1
|
public List<User> selectPage(User u);
|
5.01 最后是测试了
main...请允许本人的懒 就姑且在main方法测下吧
1
2
3
4
5
6
7
|
User u= new User();
u.setPagebegin( 2 );
u.setPagesize( 3 );
System.out.println( "-u.getCount()------" +u.getCount());
List<User> l=userService.selectPage(u);
System.out.println(l.size());
System.out.println( "-u.getCount()------" +u.getCount());
|
5.02 结果 略 然后就成功了
下面附上拦截器的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
package lqb.interceptor;
import java.util.Properties;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import java.sql.*;
import lqb.bean.Common;
@Intercepts ({
@Signature (type = StatementHandler. class , method = "prepare" , args = {Connection. class }),
@Signature (type = ResultSetHandler. class , method = "handleResultSets" , args = {Statement. class })
})
public class PageInterceptor implements Interceptor {
private static final String SELECT_ID= "selectpage" ;
//插件运行的代码,它将代替原有的方法
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println( "PageInterceptor -- intercept" );
if (invocation.getTarget() instanceof StatementHandler) {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement=(MappedStatement) metaStatementHandler.getValue( "delegate.mappedStatement" );
String selectId=mappedStatement.getId();
if (SELECT_ID.equals(selectId.substring(selectId.lastIndexOf( "." )+ 1 ).toLowerCase())){
BoundSql boundSql = (BoundSql) metaStatementHandler.getValue( "delegate.boundSql" );
// 分页参数作为参数对象parameterObject的一个属性
String sql = boundSql.getSql();
Common co=(Common)(boundSql.getParameterObject());
// 重写sql
String countSql=concatCountSql(sql);
String pageSql=concatPageSql(sql,co);
System.out.println( "重写的 count sql :" +countSql);
System.out.println( "重写的 select sql :" +pageSql);
Connection connection = (Connection) invocation.getArgs()[ 0 ];
PreparedStatement countStmt = null ;
ResultSet rs = null ;
int totalCount = 0 ;
try {
countStmt = connection.prepareStatement(countSql);
rs = countStmt.executeQuery();
if (rs.next()) {
totalCount = rs.getInt( 1 );
}
} catch (SQLException e) {
System.out.println( "Ignore this exception" +e);
} finally {
try {
rs.close();
countStmt.close();
} catch (SQLException e) {
System.out.println( "Ignore this exception" + e);
}
}
metaStatementHandler.setValue( "delegate.boundSql.sql" , pageSql);
//绑定count
co.setCount(totalCount);
}
}
return invocation.proceed();
}
/**
* 拦截类型StatementHandler
*/
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this );
} else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
}
public String concatCountSql(String sql){
StringBuffer sb= new StringBuffer( "select count(*) from " );
sql=sql.toLowerCase();
if (sql.lastIndexOf( "order" )>sql.lastIndexOf( ")" )){
sb.append(sql.substring(sql.indexOf( "from" )+ 4 , sql.lastIndexOf( "order" )));
} else {
sb.append(sql.substring(sql.indexOf( "from" )+ 4 ));
}
return sb.toString();
}
public String concatPageSql(String sql,Common co){
StringBuffer sb= new StringBuffer();
sb.append(sql);
sb.append( " limit " ).append(co.getPagebegin()).append( " , " ).append(co.getPagesize());
return sb.toString();
}
public void setPageCount(){
}
}
|
最后是下载地址:mybatisResolve.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/jethypc/p/5149183.html