java的注解和反射学了一直没有用到,主要是框架帮我们封装好了,那就好了,仿写框架就可以开拓新思路
仿mybatis写一个简易的orm框架
注解 (sql注解)
/**
* @author
* sql操作
*运行时检查
*注解标记的位置,在方法上
* */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
String value();
}
mapper接口
/**
* @author cainiao
* */
public interface UserMapper {
@Select(value = "select * from user where id = #{id}")
User select(int id);
@Insert(value = "insert into user () values ()")
void insert(User user);
void update(User user);
void delete(int id);
}
jdbc的工具类,为了简单,就不用数据库连接池
/**
* @author 连接数据库
*/
public class JDBCConfig {
private static String url = null;
private static String driver = null;
private static String username = null;
private static String password = null;
private static final String file = "db.properties";
static {
try {
InputStream input = JDBCConfig.class.getClassLoader().getResourceAsStream(file);
Properties properties = new Properties();
properties.load(input);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws Exception{
Class.forName(driver);
return DriverManager.getConnection(url, username, password);
}
public static void getClose(Connection conn, PreparedStatement ps, ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
rs=null;
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
ps = null;
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
conn = null;
}
}
}
}
包装数据的工具类
/**
* @author cainiao
* 封装返回数据
*/
public class MapperUtil {
//增 删 改
public static int update(String sql,Object...values) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
int rows = -1 ;
try {
conn = JDBCConfig.getConnection();
ps = conn.prepareStatement(sql);
int len = values.length;
for(int i = 0;i List query(Class clazz, String sql, Object[] values) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
List beans = new ArrayList<>();
try {
conn = JDBCConfig.getConnection();
ps = conn.prepareStatement(sql);
int valueCount = values.length;
for (int i = 0; i < valueCount; i++) {
ps.setObject(i + 1, values[i]);
}
rs = ps.executeQuery();
ResultSetMetaData meta = rs.getMetaData();
int colum = meta.getColumnCount();
while (rs.next()) {
T bean = clazz.newInstance();
for (int i = 0; i < colum; i++) {
String label = meta.getColumnName(i + 1);
Field field = bean.getClass().getDeclaredField(label);
field.setAccessible(true);
Object value = rs.getObject(label);
field.set(bean, value);
}
beans.add(bean);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCConfig.getClose(conn, ps, rs);
}
return beans;
}
public static void main(String[] args) {
ArrayList list = (ArrayList) MapperUtil.query(User.class,"select * from user where id = ?",new Object[]{19});
for (Object object:list){
System.out.println((User)object);
}
}
}
简单的java对象
@Table(value = "user")
public class User {
@Property(value = "id")
private int id;
private String username;
private String password;
private String salt;
private int state;
private String email;
private String phone;
private Date created;
private Date modified;
}
mapper接口没有实现类,要实现其功能需要用到jdk动态代理,这里代理不是做切面用,而是拿到接口的方法的各种参数
jdk动态代理
/**
* @author jdk动态代理
*/
public class MapperProxy implements InvocationHandler {
private Class target;
/**
*存放截取过程中的sql片段
*/
static List list = new ArrayList<>();
public MapperProxy(Class target) {
this.target = target;
}
/**
* 拿到接口类
* 代理类
* 调用的方法
* 方法的参数值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取返回值类型
Type type = method.getGenericReturnType();
//获取参数类型
Type[] types = method.getGenericParameterTypes();
//变量名
Parameter[] parameters = method.getParameters();
//返回信息
Object object = null;
Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
String name = annotation.annotationType().getSimpleName();
String sql = null;
switch (name) {
case "Select":
sql = method.getDeclaredAnnotation(Select.class).value();
object = select(sql, type, args, parameters);
break;
case "Insert":
sql = method.getDeclaredAnnotation(Insert.class).value();
break;
case "Update":
sql = method.getDeclaredAnnotation(Select.class).value();
break;
case "Delete":
sql = method.getDeclaredAnnotation(Select.class).value();
break;
default:
}
}
return object;
}
/**
* 查询方法
*/
private Object select(String sql, Type type, Object[] args, Parameter[] parameters) throws ClassNotFoundException {
Class> clazz = Class.forName("com.orm.pojo.User");
StringBuilder sb = new StringBuilder();
jiequ(sql);
for (int i = 0; i < args.length; i++) {
sb.append(list.get(i));
}
System.out.println(sb);
//转为string ,不转会越界报错
sql = sb + "";
//执行sql
List objects = MapperUtil.query(clazz, sql, args);
if (objects.size() == 1) {
try {
return objects.get(0);
} catch (Exception e) {
e.printStackTrace();
}
}
return objects;
}
private void insert(Type type, Type[] types, Object[] args) {
}
private void update(Type type, Type[] types, Object[] args) {
}
private void delete(Type type, Type[] types, Object[] args) {
}
/**
* sql截取
*/
public void jiequ(String sql) {
if (sql.contains("#")) {
String[] sqls = sql.split("and", 2);
for (int i = 0; i < sqls.length; i++) {
if (i == 0) {
String[] temps = sqls[i].split("\\#");
for (int j = 0; j < sqls.length; j++) {
if (j == 0) {
list.add(temps[j] + "?");
}
}
} else {
jiequ(sqls[i]);
}
}
}
}
public static void main(String[] args) {
}
}
这里stringbuilder必须先转为String,不然prepareStatement会报越界错误
创建代理的类
/**
* @author
* */
public class MapperFactory {
public static T newInstance(Class target){
MapperProxy mapperProxy = new MapperProxy(target);
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{target},mapperProxy);
}
}
测试类
/**
* @author
* */
public class UserService {
/**
* 注入mapper
* */
private UserMapper userMapper = MapperFactory.newInstance(UserMapper.class);
public void get(int id){
User user = userMapper.select(id);
System.out.println(user);
}
public static void main(String[] args) {
UserService userService = new UserService();
userService.get(19);
}
}
测试
还有不足,引用pojo类没有动态的获取
github:https://github.com/cailonghao/Imitation-writing