小白个人对于泛型Dao的理解是:实体类实现泛型接口,Dao的实现类实现Dao泛型接口,在Dao实现类中通过JDBC技术实现对数据库数据进行增删改查操作,其中只能使用Java类反射技术获取相应的值。
需要的jar包:连接数据库的驱动包
创建实体类的泛型接口,不需要创建方法
public interface Entity<T> {
}
User实体类实现泛型接口,为了方便理解就写了三个实体类的属性,并为他们生成get和set方法,重写toString方法
public class Users implements Entity,Serializable
private int id;
private String name;
private String pwd;
泛型Dao接口的编写:
public interface Dao {
public int insert(Entity e);//添加
public int update(Entity e);//更新
public int delect(Entity e);//删除
public List<Entity> selectAll(Entity e);//查询,返回集合
public Entity selectById(Entity e);//查询,单个返回
Dao实现类的编写:
(由于异常较多,故把一些tr-catch删除了)
一些常用的属性设置:
private String SQl_INSERT="insert";
private String SQL_UPDATE="update";
private String SQL_DELETE="delete";
private String SQL_SELECT="select";
private Class clazz;
private String tableName;
private Method[] methods;
private Field[] field;
private Connection conn;
private String sql;
类中insert方法的编写
public int insert(Entity e){
//(获取类)判断是哪一个类使用insert方法
clazz=e.getClass();
//获得表名(实体类的名字和表名相同,表名是小写):先获取传进的类名,转化成小写
tableName = clazz.getSimpleName().toLowerCase();
//获取实体类的方法
//methods = clazz.getDeclaredMethods();
//获取对应的属性
field = clazz.getDeclaredFields();
//获取实体类的对象
//Object Dx = clazz.newInstance();
//设置字段
String zd = "";
//设置数值
String sz = "";
//中间替代物,至于为什么设置替代物,因为在遍历的时候循环赋值invoke返回值强转为String类型时会丢失一些,集体原因还是弄不明白
Object o = "";
//根据获取的属性数量进行循环,通过切割再拼接的方法完成SQL语句
for(int i = 0;i<field.length;i++){
if(!field[i].getName().equalsIgnoreCase("id")){
zd += ","+field[i].getName();
sz ="get"+field[i].getName().substring(0, 1).toUpperCase()+field[i].getName().substring(1);
o += ",'"+ clazz.getMethod(sz).invoke(e)+"'";
}
}
}
//去掉逗号
zd = zd.substring(1);
sz = (String) o;
sz = sz.substring(1);
conn = ConnectionManager.getConn();
PreparedStatement ps = null;
//String 获取数组里的字段 在插入
sql = SQl_INSERT+" into "+tableName+"("+zd+")"+"values("+sz+")";
ps = conn.prepareStatement(sql);
ps.execute();
//释放资源
ConnectionManager.release(ps, null);
}
return 1;
}
update方法的编写:
public int update(Entity e) {
//假如通过id查询修改
//update table set 字段 = 字段 where 字段 = 条件 ;
clazz = e.getClass();
tableName = clazz.getSimpleName().toLowerCase();
field = clazz.getDeclaredFields();
methods = clazz.getMethods();
String zd = "";
Object o = "";
conn = ConnectionManager.getConn();
PreparedStatement ps = null;
//一个字段一个字段的修改,即一个字段一个SQL语句
//获取需要修改的用户的id
Object id = clazz.getMethod("getId").invoke(e);
for(int i =1 ;i<field.length;i++){
if(!field[i].getName().equalsIgnoreCase("id"))
sql = SQL_UPDATE+" "+tableName+" set "+field[i].getName()+" = ? "+"where id ="+id;
ps = conn.prepareStatement(sql);
zd = "get"+field[i].getName().substring(0,1).toUpperCase()+field[i].getName().substring(1);
o = clazz.getMethod(zd).invoke(e);
//判断修改的字段中,传过来的值是否存在,存在则修改不存在则不修改
if(o!=null){
ps.setObject(1, o);
ps.executeUpdate();
}
else
continue;
}
ConnectionManager.release(ps, null);
}
return 1;
}
类中delete方法的编写:
public int delete(Entity e) {
//delete from table where id = ?;
clazz = e.getClass();
tableName = clazz.getSimpleName().toLowerCase();
field = clazz.getDeclaredFields();
String zd = "";
String sz = "";
Object o = "";
for(int i = 0;i<field.length;i++){
if(field[i].getName().equals("id")){
zd = field[i].getName();
sz = "get"+field[i].getName().substring(0, 1).toUpperCase()+field[i].getName().substring(1);
o = clazz.getMethod(sz).invoke(e);
}
}
int id = (int) o;
conn = ConnectionManager.getConn();
sql = SQL_DELETE+" from "+tableName+" where id = ? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);
ps.execute();
ConnectionManager.release(ps, null);
}
return 1;
}
类中selectAll方法的编写:
public List<Entity> selectAll(Entity e) {
clazz = e.getClass();
tableName = clazz.getSimpleName().toLowerCase();
field = clazz.getDeclaredFields();
methods = clazz.getMethods();
List<Entity> list = new ArrayList<Entity>();
sql = "select * from "+tableName;
conn = ConnectionManager.getConn();
PreparedStatement ps = null;
ResultSet rs = null;
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
//获取数据库的元数据
ResultSetMetaData rsmd = rs.getMetaData();
//遍历保存数据库中对应表的列名
List<String>columnList = new ArrayList<String>();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
columnList.add(rsmd.getColumnName(i + 1));
}
//循环遍历记录
while(rs.next()){
//创建封装记录的对象
Entity e1 = (Entity) clazz.newInstance();
// 遍历一个记录中的所有列
for(int i = 0;i<columnList.size();i++){
// 获取列名
String column = columnList.get(i);
// 根据列名创建set方法
String setMethd = "set" + column.substring(0, 1).toUpperCase() + column.substring(1);
// 循环遍历methods
for (int j = 0; j < methods.length; j++) {
// 获取每一个method对象
Method m = methods[j];
// 判断m中对应的方法名和数据库中列名创建的set方法名是否形同
if(m.getName().equals(setMethd)){
// 反调set方法封装数据
m.invoke(e1, rs.getObject(column));// 获取rs中对应的值,封装到obj中
}
}
}
list.add(e1);
}
ConnectionManager.release(ps, rs);
}
return list;
}
类中selectById方法的编写:
public Entity selectById(Entity e) {
clazz = e.getClass();
tableName = clazz.getSimpleName().toLowerCase();
field = clazz.getDeclaredFields();
methods = clazz.getMethods();
sql = SQL_SELECT+" * from "+tableName+" where id = ?";
conn = ConnectionManager.getConn();
PreparedStatement ps = conn.prepareStatement(sql);
//获取用户的id封装进SQL语句中
ps.setObject(1, clazz.getMethod("getId").invoke(e));
ResultSet rs = ps.executeQuery();
//获取数据库元数据
ResultSetMetaData rsmd = rs.getMetaData();
List<String> columnList = new ArrayList<String>();
//通过列的数量遍历表对应的列名,保存在集合中
for(int i = 0;i<rsmd.getColumnCount();i++){
columnList.add(rsmd.getColumnName(i+1));
}
while(rs.next()){
for(int i = 0;i<columnList.size();i++){
//获取集合里的列名
String column = columnList.get(i);
//根据列名切割生成set方法
String setMethod = "set"+column.substring(0, 1).toUpperCase()+column.substring(1);
//获取数组中的方法名
for(int j=0;j <methods.length;j++){
//取得method对象
Method m = methods[j];
//判断反射获取所有的方法中是否有与根据列名切割成的set方法相同
if(m.getName().equals(setMethod)){
//调用set方法封装数据
m.invoke(e, rs.getObject(column));//根据列名获取结果接中对应的值
}
}
}
}
ConnectionManager.release(ps, rs);
}
return e;
}
还有就是util类的编写:
public class ConnectionManager {
private String USER = "root";
private String PASSWORD = "root";
private String URL="jdbc:mysql://localhost:3306/tdao";
private static Connection conn;
//获取数据库的一个连接
public static Connection getConn() throws ClassNotFoundException, SQLException{
if(conn == null){
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL, USER, PASSWORD);
return conn;
}
return conn;
}
//释放数据库连接资源
public static void release(PreparedStatement ps,ResultSet rs ) throws SQLException{
if(conn != null){
conn.close();
conn = null;
}
if(ps != null){
ps.close();
ps = null;
}
if(rs != null){
rs.close();
rs = null;
}
}
}
最后的测试类主要是创建对象,给对象赋值,并调用Dao实现类的方法就行啦。例子中的SQL语句有些事采用切割再拼接而成的,还有很多生成SQL语句的方法,小白没有去试验。
由于本人是小白一枚,经验少,能力不足,而且还是第一次写博客(主要想记录和分享自己的一些心得与经验),这些代码中有许多的不足或者错误,希望各位大神若是看到能指点一二,小白虚心听取意见。在编写selectAll方法的时候参考了这位大神的博客[利用反射机制查询数据库内数据,数据库内数据库类型为类型时](https://my.oschina.net/HIJAY/blog/114106),还有一些大神的博客也参考了,可是忘记了连接地址,小白非常地抱歉,希望谅解。