如果不能简单的把事情说清楚,说明你还没有完全明白。
最近学习框架的时候,一去看源码就各种懵逼与难受,所以去补了一波反射和动态代理。反射其实就是一波API,平时自己很少用到,陌生产生恐惧。
正常情况下的CRUD操作,JDBC
Bean
public class User
{
private int user_id;
private String user_name;
private String user_password;
private String user_role;
、、、各种get set
}
DAO
public class UserDAO {
private Connection conn=(Connection) ConnectFactory.getConnection();
public List<User> selectAllUser()
{
List<User> list=new ArrayList<>();
try
{
PreparedStatement st=null;
String sql="select * from user";
st=(PreparedStatement) conn.prepareStatement(sql);
ResultSet rs=st.executeQuery(sql);
while(rs.next())
{
User user=new User();
user.setUser_name(rs.getString("user_name"));
user.setUser_id(rs.getInt("user_id"));
user.setUser_password(rs.getString("user_password"));
user.setUser_role(rs.getString("user_role"));
list.add(user);
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
ConnectFactory.closeConnection();
}
return list;
}
}
那么问题来了,如果有10个表需要进行同样的操作,比如:查询表的所有信息,查询总记录数,插入一条信息等 这种通用操作的sql语句。就会用传统的JDBC操作,程序猿小哥表示ctrl+c ctrl+v 不过来。
利用反射实现CRUD操作
public class ReflexDAO {
private Connection conn=(Connection) ConnectFactory.getConnection();
/**
* 查询 所有
* @param c1
* @return
*/
public ArrayList selectAll(Class c1) //如果查询ID,加个ID参数。ID作为主键默认 在Bean属性的 第一个。
{
ArrayList list=new ArrayList();
try
{
PreparedStatement st=null;
//数据库表的名字 ==bean类的名字
String sql="select * from "+c1.getSimpleName();
st=(PreparedStatement) conn.prepareStatement(sql);
ResultSet rs=st.executeQuery(sql);
Field [] fi=c1.getDeclaredFields(); //获取到 类对象 的所有属性
while(rs.next())
{
Object ob=c1.newInstance();
for (Field field : fi) {
field.setAccessible(true);
field.set(ob, rs.getObject(field.getName()));
}
list.add(ob);
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
ConnectFactory.closeConnection();
}
return list;
}
public void insert(Object oj)
{
try
{
Class cl=oj.getClass();
PreparedStatement st=null;
Field [] fields=cl.getDeclaredFields(); //获取所有的属性
StringBuffer sf=new StringBuffer();
sf.append("insert into ");
sf.append(cl.getSimpleName());
sf.append("(");
for (int i=1;i<fields.length;i++) {
fields[i].setAccessible(true); //让私有的可以被访问
if(i==fields.length-1)
{
sf.append(fields[i].getName());
}
else
{
sf.append(fields[i].getName()+",");
}
}
sf.append(") value(");
for (int i=1;i<fields.length;i++) {
if(i==fields.length-1)
{
sf.append("?)");
}
else
{
sf.append("?,");
}
}
System.out.println(sf);
st=(PreparedStatement) conn.prepareStatement(sf.toString());
for (int i=1;i<fields.length;i++)
{
st.setObject(i, fields[i].get(oj));
}
st.executeUpdate();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
ConnectFactory.closeConnection();
}
}
这样子,就能够实现一个方法到处浪。
值得注意的是:
数据库的表名 要和类名保持一致,如果不一致的话,需要用配置文件进行映射,框架一般也是这么做的。
这种方法的反射我只 用了 属性去反射,存在一些局限性:如果属性的个数多余表列属性的个数,那么就会报错。
网友评论