DAO数据访问对象data access object的缩写,用于进行数据操作的封装,在Java程序开发中属于标准开 发架构中的持久层的设计模式。DAO模式是标准JavaEE设计模式之一,用途在于将底层的数据访问操作和高层的业务逻辑分离开。 典型的DAO模式的组成 一个DAO工厂类,一个DAO接口 实现了DAO接口的多种实现类 数据传输对象DTO,有时简称为VO。
运用JAVA反射机制,获取实体类定义的字段和方法实现一个万能的DAO模式,IBaseDao接口和BaseDaoImpl类定义类通用的增删改查方法,只需用具体的实现类去继承通用方法,泛型传入具体的类型即可。
结构:
dao类:
IBaseDao:一个接口(定义通用的增删改查方法),通过接口暴漏当前层中允许调用的方法
public interface IBaseDao<T extends Serializable> {
public int save(T t);//增
public int delete(T t);//删
public int update(T t);//改
public List<T> query(T t);//按id查询
public List<T> findByExample(T t);//整表查询
}
BaseDaoImpl:实现IBaseDao接口定义的方法:
public abstract class BaseDaoImpl<T extends Serializable> implements IBaseDao<T> {
private Class<T> clazz;
@SuppressWarnings({ "unchecked", "rawtypes" })
public BaseDaoImpl() {
Class<? extends IBaseDao> clz=this.getClass();
ParameterizedType pt =(ParameterizedType)clz.getGenericSuperclass();
clazz = (Class) pt.getActualTypeArguments()[0];
}
@Override
//insert into tb_user() values();
public int save(T obj) {
StringBuilder sb1 = new StringBuilder("insert into tb_");
sb1.append(clazz.getSimpleName().toLowerCase()).append("(");
StringBuilder sb2=new StringBuilder(") values (");
Field[] fs = clazz.getDeclaredFields();//获取当前类的所有字段
List<Object> params = new ArrayList<>();
try {
for (int i = 0; i < fs.length; i++) {
Field f = fs[i];
f.setAccessible(true);
Object val = f.get(obj);
if (val!=null) {
sb1.append(f.getName()).append(",");
sb2.append("?,");
params.add(val);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
if (sb1.toString().endsWith(",")) {
sb1.deleteCharAt(sb1.length()-1);
}
if (sb2.toString().endsWith(",")) {
sb2.deleteCharAt(sb2.length()-1);
}
String sql = sb1.toString()+sb2.toString()+")";
return update(sql, params.toArray());
}
public int update(String sql,Object...params) {
int res=0;
try {
res = JdbcUtils.executeUpdate(sql, params);
} catch (Exception e) {
JdbcUtils.releaseConnention();
}
return res;
}
@Override
//delete from tb_user where id=?
public int delete(T obj) {
StringBuilder sb1 = new StringBuilder("delete from tb_");
sb1.append(clazz.getSimpleName().toLowerCase()).append(" where 1=1 ");
Field [] fs = clazz.getDeclaredFields();
List<Object> params = new ArrayList<>();
try {
for (int i = 0; i < fs.length; i++) {
Field f = fs[i];
f.setAccessible(true);
Object val = f.get(obj);
if (f!=null && val!=null) {
sb1.append(" and ").append(f.getName()).append(" =? ");
params.add(val);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
String sql = sb1.toString();
return update(sql, params.toArray());
}
@Override
//update tb_user set name=?,password=? where id=?;
public int update(T obj) {
StringBuilder sb1 = new StringBuilder("update tb_");
sb1.append(clazz.getSimpleName().toLowerCase()).append(" set ");
StringBuilder sb2 = new StringBuilder(" where ");
Field [] fs = clazz.getDeclaredFields();
List<Object> params = new ArrayList<>();
try {
for (int i = 1; i < fs.length; i++) {
Field f = fs[i];
f.setAccessible(true);
Object val = f.get(obj);
if (f!=null && val!=null) {
sb1.append(f.getName()).append(" =?,");
params.add(val);
}
}
Field f = fs[0];
f.setAccessible(true);
sb2.append(f.getName()).append(" =? ");
Object val = f.get(obj);
params.add(val);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (sb1.toString().endsWith(",")) {
sb1.deleteCharAt(sb1.length()-1);
}
String sql = sb1.toString()+sb2.toString();
return update(sql, params.toArray());
}
@Override
public List<T> query(T obj) {
List<T> res = new ArrayList<>();
try {
StringBuilder sb = new StringBuilder("select * from tb_");
sb.append(clazz.getSimpleName().toLowerCase()).append(" where 1=1 ");
Field[] fs = clazz.getDeclaredFields();
List<Object> params = new ArrayList<>();
for (int i = 0; i < fs.length; i++) {
Field f = fs[i];
f.setAccessible(true);
Object val = f.get(obj);
if (val!=null) {
sb.append(" and ").append(f.getName()).append(" =? ");
params.add(val);
}
}
ResultSet rs = JdbcUtils.executeQuery(sb.toString(),params.toArray());
while (rs.next()) {
ResultSetMetaData rsemd = rs.getMetaData();
T t = clazz.newInstance();
for (int i = 1; i <=rsemd.getColumnCount(); i++) {
String fieldName = rsemd.getColumnLabel(i);
Field f = clazz.getDeclaredField(fieldName);
f.setAccessible(true);
f.set(t, rs.getObject(i));
}
res.add(t);
}
rs.close();
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.releaseConnention();
}
return res;
}
@Override
public List<T> findByExample(T obj){
List<T> res = new ArrayList<>();
List<Object> params = new ArrayList<>();
StringBuilder sql = new StringBuilder("select * from tb_user;");
try{
ResultSet rs = JdbcUtils.executeQuery(sql.toString(),params.toArray());
while (rs.next()) {
ResultSetMetaData rsemd = rs.getMetaData();
T t = clazz.newInstance();
for (int i = 1; i <=rsemd.getColumnCount(); i++) {
String fieldName = rsemd.getColumnLabel(i);
Field f = clazz.getDeclaredField(fieldName);
f.setAccessible(true);
f.set(t, rs.getObject(i));
}
res.add(t);
}
rs.close();
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtils.releaseConnention();
}
return res;
}
}
IUserDao和UserDaoImpl:
public interface IUserDao extends IBaseDao<User> {
//如果需要增加方法,可以在这里声明
}
public class UserDaoImpl extends BaseDaoImpl<User> implements IUserDao {
如果有特殊方法,则在这里实现,实际上通用的增删改查方法已经从BaseDao中继承
}
实体类entity:
user:根据对应的表结构定义实体类类名称和表名称对应,属性名称和字段名称对应 类中的属性不要使用简单类型,判断的需要 setObject
public class User implements Serializable {
private Integer id;
private String username;
private String password;
public User() {
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
工厂类Factory:
Factory:
public class User implements Serializable {
private Long id;
private String username;
private String password;
public User() {
}
public User(Long id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
工具类Util类:
public class JdbcUtils {
private JdbcUtils() {
}
private static DataSource ds;
private static final ThreadLocal<Connection> ts = new ThreadLocal<>();
static {
try {
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("src/jdbc.properties");
Properties ps = new Properties();
ps.load(is);
ds = DruidDataSourceFactory.createDataSource(ps);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取链接
public static Connection getConnection() {
Connection res = ts.get();
if (res == null) {
try {
res = ds.getConnection();
ts.set(res);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
return res;
}
//释放连接
public static void releaseConnention() {
Connection conn = ts.get();
if (conn != null) {
try {
conn.close();
ts.remove();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
}
//执行增删改的方法
public static int executeUpdate(String sql, Object... params) {
try {
System.out.println(sql);
return createPreparedStatement(sql, params).executeUpdate();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
//执行查询的方法
public static ResultSet executeQuery(String sql, Object... params) {
try {
return createPreparedStatement(sql, params).executeQuery();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
//为sql语句赋值,并返回PreparedStatement对象
public static PreparedStatement createPreparedStatement(String sql, Object... params) {
try {
Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
if (params != null && params.length > 0)
for (int i = 0; i < params.length; i++)
ps.setObject(i + 1, params[i]);
System.out.println(ps);
return ps;
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
}
测试方法:
具体的数据表tb_user
mysql> desc tb_user;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(32) | NO | | NULL | |
| password | varchar(32) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.02 sec)
mysql> select * from tb_user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | 张三 | ZS123456 |
| 2 | 李四 | LS123456 |
| 3 | 王五 | WW123456 |
+----+----------+----------+
3 rows in set (0.00 sec)
1.测试增加数据的方法:save(T obj)
IUserDao dao =DaoFactory.getUserDao();
User user1=new User(4L,"赵六","ZL123456");
int num=dao.save(user1);
if (num >0) {
System.out.println("插入成功!");
}else {
System.out.println("插入失败!");
}
mysql> select * from tb_user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | 张三 | ZS123456 |
| 2 | 李四 | LS123456 |
| 3 | 王五 | WW123456 |
| 4 | 赵六 | ZL123456 |
+----+----------+----------+
4 rows in set (0.00 sec)
mysql>
2.测试删除方法delet(T obj)
IUserDao dao =DaoFactory.getUserDao();
User user1=new User();
user1.setId(4L);
int num=dao.delete(user1);
if (num >0) {
System.out.println("删除成功!");
}else {
System.out.println("删除失败!");
}
mysql> select * from tb_user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | 张三 | ZS123456 |
| 2 | 李四 | LS123456 |
| 3 | 王五 | WW123456 |
+----+----------+----------+
3 rows in set (0.00 sec)
3.测试修改方法delet(T obj)
IUserDao dao =DaoFactory.getUserDao();
User user1=new User();
user1.setId(1L);
user1.setUsername("张小三");
int num=dao.update(user1);
if (num >0) {
System.out.println("修改成功!");
}else {
System.out.println("修改失败!");
}
mysql> select * from tb_user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | 张小三 | ZS123456 |
| 2 | 李四 | LS123456 |
| 3 | 王五 | WW123456 |
+----+----------+----------+
3 rows in set (0.00 sec)
4.测试查询方法:
1.测试整表查询
mysql> select * from tb_user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | 张小三 | ZS123456 |
| 2 | 李四 | LS123456 |
| 3 | 王五 | WW123456 |
+----+----------+----------+
3 rows in set (0.00 sec)
2.测试按id查询:
IUserDao dao =DaoFactory.getUserDao();
User user1=new User();
user1.setId(1);
List<User> list = dao.query(user1);
for (User temp:list) {
System.out.println(temp);
}