MyBatis
实现思路
1.自定义注解
2.通过动态代理的方法来初始化接口并拦截其带有注解的方法
3.拆分注解中的sql,以原生的JDBC的方式执行拼接后的sql
引入Pom文件
< project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns: xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion> 4.0 .0 < / modelVersion>
< groupId> com. cy< / groupId>
< artifactId> my- mybatis< / artifactId>
< version> 0.0 .1 - SNAPSHOT< / version>
< dependencies>
< ! -- mybatis核心包 -- >
< dependency>
< groupId> org. mybatis< / groupId>
< artifactId> mybatis< / artifactId>
< version> 3.4 .5 < / version>
< / dependency>
< ! -- 引入Spring- AOP等相关Jar -- >
< dependency>
< groupId> org. springframework< / groupId>
< artifactId> spring- core< / artifactId>
< version> 3.0 .6 . RELEASE< / version>
< / dependency>
< dependency>
< groupId> org. springframework< / groupId>
< artifactId> spring- context< / artifactId>
< version> 3.0 .6 . RELEASE< / version>
< / dependency>
< dependency>
< groupId> org. springframework< / groupId>
< artifactId> spring- aop< / artifactId>
< version> 3.0 .6 . RELEASE< / version>
< / dependency>
< dependency>
< groupId> org. springframework< / groupId>
< artifactId> spring- orm< / artifactId>
< version> 3.0 .6 . RELEASE< / version>
< / dependency>
< dependency>
< groupId> org. aspectj< / groupId>
< artifactId> aspectjrt< / artifactId>
< version> 1.6 .1 < / version>
< / dependency>
< dependency>
< groupId> aspectj< / groupId>
< artifactId> aspectjweaver< / artifactId>
< version> 1.5 .3 < / version>
< / dependency>
< dependency>
< groupId> cglib< / groupId>
< artifactId> cglib< / artifactId>
< version> 2.1 _2< / version>
< / dependency>
< ! -- https: / / mvnrepository. com/ artifact/ com. mchange/ c3p0 -- >
< dependency>
< groupId> com. mchange< / groupId>
< artifactId> c3p0< / artifactId>
< version> 0.9 .5 .2 < / version>
< / dependency>
< ! -- https: / / mvnrepository. com/ artifact/ mysql/ mysql- connector- java -- >
< dependency>
< groupId> mysql< / groupId>
< artifactId> mysql- connector- java< / artifactId>
< version> 5.1 .37 < / version>
< / dependency>
< ! -- https: / / mvnrepository. com/ artifact/ asm/ asm -- >
< dependency>
< groupId> asm< / groupId>
< artifactId> asm< / artifactId>
< version> 3.3 .1 < / version>
< / dependency>
< / dependencies>
< / project>
导入SQL文件
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0 ;
DROP TABLE IF EXISTS ` t_users` ;
CREATE TABLE ` t_users` (
` name` varchar ( 255 ) DEFAULT NULL ,
` id` int ( 11 ) NOT NULL AUTO_INCREMENT ,
` age` int ( 11 ) DEFAULT NULL ,
PRIMARY KEY ( ` id` )
) ENGINE = InnoDB AUTO_INCREMENT = 30 DEFAULT CHARSET = utf8;
BEGIN ;
INSERT INTO ` t_users` VALUES ( 'test001' , 28 , 20 ) ;
INSERT INTO ` t_users` VALUES ( 'test002' , 29 , 21 ) ;
COMMIT ;
SET FOREIGN_KEY_CHECKS = 1 ;
创建实体类
public class User {
private Integer id;
private String userName;
private Integer userAge;
public String getUserName ( ) {
return userName;
}
public void setUserName ( String userName) {
this . userName = userName;
}
public Integer getUserAge ( ) {
return userAge;
}
public void setUserAge ( Integer userAge) {
this . userAge = userAge;
}
public Integer getId ( ) {
return id;
}
public void setId ( Integer id) {
this . id = id;
}
}
自定义注解
@Documented
@Retention ( RetentionPolicy. RUNTIME)
@Target ( ElementType. METHOD)
public @interface ExtInsert {
String value ( ) ;
}
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
@Documented
@Retention ( RetentionPolicy. RUNTIME)
@Target ( ElementType. PARAMETER)
public @interface ExtParam {
String value ( ) ;
}
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
@Documented
@Retention ( RetentionPolicy. RUNTIME)
@Target ( ElementType. METHOD)
public @interface ExtSelect {
String value ( ) ;
}
封装JDBCUtils
public final class JDBCUtils {
private static String connect;
private static String driverClassName;
private static String URL;
private static String username;
private static String password;
private static boolean autoCommit;
private static Connection conn;
static {
config ( ) ;
}
private static void config ( ) {
driverClassName = "com.mysql.jdbc.Driver" ;
URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8" ;
username = "root" ;
password = "root" ;
autoCommit = false ;
}
private static boolean load ( ) {
try {
Class. forName ( driverClassName) ;
return true ;
} catch ( ClassNotFoundException e) {
System. out. println ( "驱动类 " + driverClassName + " 加载失败" ) ;
}
return false ;
}
private static boolean invalid ( ) {
if ( conn != null) {
try {
if ( conn. isClosed ( ) || ! conn. isValid ( 3 ) ) {
return true ;
}
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
return false ;
} else {
return true ;
}
}
public static Connection connect ( ) {
if ( invalid ( ) ) {
load ( ) ;
try {
conn = DriverManager. getConnection ( URL, username, password) ;
} catch ( SQLException e) {
System. out. println ( "建立 " + connect + " 数据库连接失败 , " + e. getMessage ( ) ) ;
}
}
return conn;
}
public static void transaction ( ) {
try {
conn. setAutoCommit ( autoCommit) ;
} catch ( SQLException e) {
System. out. println ( "设置事务的提交方式为 : " + ( autoCommit ? "自动提交" : "手动提交" ) + " 时失败: " + e. getMessage ( ) ) ;
}
}
public static Statement statement ( ) {
Statement st = null;
connect ( ) ;
transaction ( ) ;
try {
st = conn. createStatement ( ) ;
} catch ( SQLException e) {
System. out. println ( "创建 Statement 对象失败: " + e. getMessage ( ) ) ;
}
return st;
}
private static PreparedStatement prepare ( String SQL, boolean autoGeneratedKeys) {
PreparedStatement ps = null;
connect ( ) ;
transaction ( ) ;
try {
if ( autoGeneratedKeys) {
ps = conn. prepareStatement ( SQL, Statement. RETURN_GENERATED_KEYS) ;
} else {
ps = conn. prepareStatement ( SQL) ;
}
} catch ( SQLException e) {
System. out. println ( "创建 PreparedStatement 对象失败: " + e. getMessage ( ) ) ;
}
return ps;
}
public static ResultSet query ( String SQL, List< Object> params) {
if ( SQL == null || SQL. trim ( ) . isEmpty ( ) || ! SQL. trim ( ) . toLowerCase ( ) . startsWith ( "select" ) ) {
throw new RuntimeException ( "你的SQL语句为空或不是查询语句" ) ;
}
ResultSet rs = null;
if ( params. size ( ) > 0 ) {
PreparedStatement ps = prepare ( SQL, false ) ;
try {
for ( int i = 0 ; i < params. size ( ) ; i++ ) {
ps. setObject ( i + 1 , params. get ( i) ) ;
}
rs = ps. executeQuery ( ) ;
} catch ( SQLException e) {
System. out. println ( "执行SQL失败: " + e. getMessage ( ) ) ;
}
} else {
Statement st = statement ( ) ;
try {
rs = st. executeQuery ( SQL) ;
} catch ( SQLException e) {
System. out. println ( "执行SQL失败: " + e. getMessage ( ) ) ;
}
}
return rs;
}
private static Object typeof ( Object o) {
Object r = o;
if ( o instanceof java. sql. Timestamp ) {
return r;
}
if ( o instanceof java. util. Date ) {
java. util. Date d = ( java. util. Date) o;
r = new java. sql. Date ( d. getTime ( ) ) ;
return r;
}
if ( o instanceof Character || o. getClass ( ) == char . class ) {
r = String. valueOf ( o) ;
return r;
}
return r;
}
public static boolean execute ( String SQL, Object. . . params) {
if ( SQL == null || SQL. trim ( ) . isEmpty ( ) || SQL. trim ( ) . toLowerCase ( ) . startsWith ( "select" ) ) {
throw new RuntimeException ( "你的SQL语句为空或有错" ) ;
}
boolean r = false ;
SQL = SQL. trim ( ) ;
SQL = SQL. toLowerCase ( ) ;
String prefix = SQL. substring ( 0 , SQL. indexOf ( " " ) ) ;
String operation = "" ;
switch ( prefix) {
case "create" :
operation = "create table" ;
break ;
case "alter" :
operation = "update table" ;
break ;
case "drop" :
operation = "drop table" ;
break ;
case "truncate" :
operation = "truncate table" ;
break ;
case "insert" :
operation = "insert :" ;
break ;
case "update" :
operation = "update :" ;
break ;
case "delete" :
operation = "delete :" ;
break ;
}
if ( params. length > 0 ) {
PreparedStatement ps = prepare ( SQL, false ) ;
Connection c = null;
try {
c = ps. getConnection ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
try {
for ( int i = 0 ; i < params. length; i++ ) {
Object p = params[ i] ;
p = typeof ( p) ;
ps. setObject ( i + 1 , p) ;
}
ps. executeUpdate ( ) ;
commit ( c) ;
r = true ;
} catch ( SQLException e) {
System. out. println ( operation + " 失败: " + e. getMessage ( ) ) ;
rollback ( c) ;
}
} else {
Statement st = statement ( ) ;
Connection c = null;
try {
c = st. getConnection ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
try {
st. executeUpdate ( SQL) ;
commit ( c) ;
r = true ;
} catch ( SQLException e) {
System. out. println ( operation + " 失败: " + e. getMessage ( ) ) ;
rollback ( c) ;
}
}
return r;
}
public static int insert ( String SQL, boolean autoGeneratedKeys, List< Object> params) {
int var = - 1 ;
if ( SQL == null || SQL. trim ( ) . isEmpty ( ) ) {
throw new RuntimeException ( "你没有指定SQL语句,请检查是否指定了需要执行的SQL语句" ) ;
}
if ( ! SQL. trim ( ) . toLowerCase ( ) . startsWith ( "insert" ) ) {
System. out. println ( SQL. toLowerCase ( ) ) ;
throw new RuntimeException ( "你指定的SQL语句不是插入语句,请检查你的SQL语句" ) ;
}
SQL = SQL. trim ( ) ;
SQL = SQL. toLowerCase ( ) ;
if ( params. size ( ) > 0 ) {
PreparedStatement ps = prepare ( SQL, autoGeneratedKeys) ;
Connection c = null;
try {
c = ps. getConnection ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
try {
for ( int i = 0 ; i < params. size ( ) ; i++ ) {
Object p = params. get ( i) ;
p = typeof ( p) ;
ps. setObject ( i + 1 , p) ;
}
int count = ps. executeUpdate ( ) ;
if ( autoGeneratedKeys) {
ResultSet rs = ps. getGeneratedKeys ( ) ;
if ( rs. next ( ) ) {
var = rs. getInt ( 1 ) ;
}
} else {
var = count;
}
commit ( c) ;
} catch ( SQLException e) {
System. out. println ( "数据保存失败: " + e. getMessage ( ) ) ;
rollback ( c) ;
}
} else {
Statement st = statement ( ) ;
Connection c = null;
try {
c = st. getConnection ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
try {
int count = st. executeUpdate ( SQL) ;
if ( autoGeneratedKeys) {
ResultSet rs = st. getGeneratedKeys ( ) ;
if ( rs. next ( ) ) {
var = rs. getInt ( 1 ) ;
}
} else {
var = count;
}
commit ( c) ;
} catch ( SQLException e) {
System. out. println ( "数据保存失败: " + e. getMessage ( ) ) ;
rollback ( c) ;
}
}
return var;
}
private static void commit ( Connection c) {
if ( c != null && ! autoCommit) {
try {
c. commit ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
}
}
private static void rollback ( Connection c) {
if ( c != null && ! autoCommit) {
try {
c. rollback ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
}
}
public static void release ( Object cloaseable) {
if ( cloaseable != null) {
if ( cloaseable instanceof ResultSet ) {
ResultSet rs = ( ResultSet) cloaseable;
try {
rs. close ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
}
if ( cloaseable instanceof Statement ) {
Statement st = ( Statement) cloaseable;
try {
st. close ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
}
if ( cloaseable instanceof Connection ) {
Connection c = ( Connection) cloaseable;
try {
c. close ( ) ;
} catch ( SQLException e) {
e. printStackTrace ( ) ;
}
}
}
}
}
封装SQLUtils
public class SQLUtils {
public static String[ ] sqlInsertParameter ( String sql) {
int startIndex = sql. indexOf ( "values" ) ;
int endIndex = sql. length ( ) ;
String substring = sql. substring ( startIndex + 6 , endIndex) . replace ( "(" , "" ) . replace ( ")" , "" ) . replace ( "#{" , "" )
. replace ( "}" , "" ) ;
String[ ] split = substring. split ( "," ) ;
return split;
}
public static List< String> sqlSelectParameter ( String sql) {
int startIndex = sql. indexOf ( "where" ) ;
int endIndex = sql. length ( ) ;
String substring = sql. substring ( startIndex + 5 , endIndex) ;
String[ ] split = substring. split ( "and" ) ;
List< String> listArr = new ArrayList < > ( ) ;
for ( String string : split) {
String[ ] sp2 = string. split ( "=" ) ;
listArr. add ( sp2[ 0 ] . trim ( ) ) ;
}
return listArr;
}
public static String parameQuestion ( String sql, String[ ] parameterName) {
for ( int i = 0 ; i < parameterName. length; i++ ) {
String string = parameterName[ i] ;
sql = sql. replace ( "#{" + string + "}" , "?" ) ;
}
return sql;
}
public static String parameQuestion ( String sql, List< String> parameterName) {
for ( int i = 0 ; i < parameterName. size ( ) ; i++ ) {
String string = parameterName. get ( i) ;
sql = sql. replace ( "#{" + string + "}" , "?" ) ;
}
return sql;
}
}
创建提供动态代理的接口
public class SqlSession {
public static < T> T getMapper ( Class classz ) {
return ( T) Proxy. newProxyInstance ( classz. getClassLoader ( ) , new Class [ ] { classz } ,
new MyInvocationHandlerMbatis ( classz) ) ;
}
}
代理类 通过反射持久层接口
public class MyInvocationHandlerMbatis implements InvocationHandler {
private Object object;
public MyInvocationHandlerMbatis ( Object object) {
this . object = object;
}
public Object invoke ( Object proxy, Method method, Object[ ] args) throws Throwable {
System. out. println ( "使用动态代理技术拦截接口方法开始" ) ;
ExtInsert extInsert = method. getDeclaredAnnotation ( ExtInsert. class ) ;
if ( extInsert != null) {
return extInsert ( extInsert, proxy, method, args) ;
}
ExtSelect extSelect = method. getDeclaredAnnotation ( ExtSelect. class ) ;
if ( extSelect != null) {
String selectSQL = extSelect. value ( ) ;
ConcurrentHashMap< Object, Object> paramsMap = paramsMap ( proxy, method, args) ;
List< String> sqlSelectParameter = SQLUtils. sqlSelectParameter ( selectSQL) ;
List< Object> sqlParams = new ArrayList < > ( ) ;
for ( String parameterName : sqlSelectParameter) {
Object parameterValue = paramsMap. get ( parameterName) ;
sqlParams. add ( parameterValue) ;
}
String newSql = SQLUtils. parameQuestion ( selectSQL, sqlSelectParameter) ;
System. out. println ( "newSQL:" + newSql + ",sqlParams:" + sqlParams. toString ( ) ) ;
ResultSet res = JDBCUtils. query ( newSql, sqlParams) ;
if ( ! res. next ( ) ) {
return null;
}
res. previous ( ) ;
Class< ? > returnType = method. getReturnType ( ) ;
Object object = returnType. newInstance ( ) ;
while ( res. next ( ) ) {
Field[ ] declaredFields = returnType. getDeclaredFields ( ) ;
for ( Field field : declaredFields) {
String fieldName = field. getName ( ) ;
Object fieldValue = res. getObject ( fieldName) ;
field. setAccessible ( true ) ;
field. set ( object, fieldValue) ;
}
}
return object;
}
return null;
}
private Object extInsert ( ExtInsert extInsert, Object proxy, Method method, Object[ ] args) {
String insertSql = extInsert. value ( ) ;
ConcurrentHashMap< Object, Object> paramsMap = paramsMap ( proxy, method, args) ;
String[ ] sqlInsertParameter = SQLUtils. sqlInsertParameter ( insertSql) ;
List< Object> sqlParams = sqlParams ( sqlInsertParameter, paramsMap) ;
String newSQL = SQLUtils. parameQuestion ( insertSql, sqlInsertParameter) ;
System. out. println ( "newSQL:" + newSQL + ",sqlParams:" + sqlParams. toString ( ) ) ;
return JDBCUtils. insert ( newSQL, false , sqlParams) ;
}
private List< Object> sqlParams ( String[ ] sqlInsertParameter, ConcurrentHashMap< Object, Object> paramsMap) {
List< Object> sqlParams = new ArrayList < > ( ) ;
for ( String paramName : sqlInsertParameter) {
Object paramValue = paramsMap. get ( paramName) ;
sqlParams. add ( paramValue) ;
}
return sqlParams;
}
private ConcurrentHashMap< Object, Object> paramsMap ( Object proxy, Method method, Object[ ] args) {
ConcurrentHashMap< Object, Object> paramsMap = new ConcurrentHashMap < > ( ) ;
Parameter[ ] parameters = method. getParameters ( ) ;
for ( int i = 0 ; i < parameters. length; i++ ) {
Parameter parameter = parameters[ i] ;
ExtParam extParam = parameter. getDeclaredAnnotation ( ExtParam. class ) ;
if ( extParam != null) {
String paramName = extParam. value ( ) ;
Object paramValue = args[ i] ;
paramsMap. put ( paramName, paramValue) ;
}
}
return paramsMap;
}
public Object extInsertSQL ( ) {
return object;
}
}
测试类
public class Test0003 {
public static void main ( String[ ] args) {
UserMapper userMapper = SqlSession. getMapper ( UserMapper. class ) ;
User selectUser = userMapper. selectUser ( "张三" , 644064 ) ;
System. out. println (
"结果:" + selectUser. getUserName ( ) + "," + selectUser. getUserAge ( ) + ",id:" + selectUser. getId ( ) ) ;
}
}