第一次笔记记录自己在广州学习到的关于Java的知识,防止自己忘记,也是通过这个方法来温习自己学到的知识这是7月3日的笔记:
DAO开发模式:英文全称Data Access Object
MVC:
M(Mode):DAO+JavaBean:专门用于与数据库打交道
C(Controller):控制器层: 不使用框架时Servlet,使用框架Struts2(Action)、springmvc(Controller),Service(业务层)
V(View):视图层
html:静态网页技术
jsp:动态网页技术
Dao:面向接口编程
DbDao dao=new MySqlDaoImpl();
案例:
建立一个关于User表的dao开发模式:
建包思路:
包名有意义、将接口业务dao放在一个dao包下、将实现接口的类放在impl包下、将实体类放在entity下,其实我觉得将大家公用的方法的dao放在一个新的包下比较好(图中的BaseDao)。
1.User实体
package com.day703.work.entity;
//实体就是封装数据库中表的属性
public class User {
private int id;
private String loginName;
private String pwd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
2.UserDao
package com.day703.work.dao;
//UserDao是一个接口,定义了基本表User的增删改查方法
import java.util.List;
import com.day703.work.entity.User;
public interface UserDao {
public List findAll();//查询表中全部数据
public int addUser(User user);//传入一个User对象进行新增,良好的扩展性,如果传入具体属性值,扩展麻烦
public int deleteUser(int id);//删除记录依据主码删除
public int updateUser(User user);
public List findCondition(User user);//按条件查询,保持良好的扩展性传入一个user对象
}
一般一个表的接口应该在其中定义对于该表的操作方法,目前看来是这样。一般这种声明方法的都会用接口的方式定义,方法定义为抽象方法由具体的实现类去实现。比如这里的UserDaoImpl.java
3.BaseDao
package com.day703.work.dao;
//BaseDao的由来就是在具体实现类实现表的抽象方法时,发现很多代码可以复用,于是提出来封装成方法放在一个父类中、这个父类就是BaseDao,里面有很多共用的方法,不过也要注意良好的扩展性。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public abstract class BaseDao {
//初始化连接数据库的信息
protected String driverClass="com.mysql.jdbc.Driver";
protected String url="jdbc:mysql://localhost:3306/ysj";
protected String userName="root";
protected String pwd="123456";
public abstract Object getEntity(ResultSet rs);
//这个方法是根据数据库获取的rs对象,取得具体的表对象。
public Connection getConnection(){//连接数据库方法
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
return DriverManager.getConnection(url,userName,pwd);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void closeAll(ResultSet rs,Statement sta,Connection conn){//释放资源的方法,注意先后顺序conn>sta>rs,由小到大关闭
try {
if(rs!=null) rs.close();
if(sta!=null) sta.close();
if(conn!=null) conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int executeUpdate(String sql,Object[] parms){
//增删改的通用方法,传入的参数为sql语句和为了设置语句集的参数的一个对象数组
Connection conn=null;
PreparedStatement sta=null;
conn=this.getConnection();//获取连接
try {
sta=conn.prepareStatement(sql);//执行sql
if(parms!=null&&parms.length>0){
for(int i=0;i1, parms[i]);
}
}//设置问号参数对应的值
int rows=sta.executeUpdate();//获取受到影响的行数
return rows;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
this.closeAll(null, sta, conn);//关闭资源
}
return 0;
}
public List executeQuery(String sql,Object[] params){
//按属性来查询对象,传入的参数为sql语句以及一个对象数组
List
BaseDao中封装了很多可能复用的方法不光是对User一个对象类,可能是扩展的其他的对象比如加一个部门之类的,连接方法以及增删改的通用方法,释放资源的方法,以及查询的方法都可以节省大量的代码量,下面给出一个UserDao的实现类。
4.UserDaoImpl
package com.day703.work.impl;
//具体的实现方法类,实现抽象接口中定义的方法
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.day703.work.dao.BaseDao;
import com.day703.work.dao.UserDao;
import com.day703.work.entity.User;
public class UserDaoImpl extends BaseDao implements UserDao {//继承在先实现在后
@Override
public List findAll() {
//全表查询方法,可以被后面条件查询代替
List list=new ArrayList();
Connection conn=null;
PreparedStatement sta=null;
ResultSet rs=null;
String sql="SELECT * FROM a_user";//查询语句
conn=this.getConnection();//获取连接省了代码
try {
sta=conn.prepareStatement(sql);
rs=sta.executeQuery();
while(rs.next()){
User user=new User();
user.setId(rs.getInt("id"));
user.setLoginName(rs.getString("loginName"));
user.setPwd(rs.getString("pwd"));
list.add(user);
}
return list;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
this.closeAll(rs, sta, conn);//关闭资源
}
return null;
}
@Override
public int addUser(User user) {
//增加一个对象到数据库,可以清楚看到封装方法的好处
String sql="insert into a_user(id,loginName,pwd) values(?,?,?)";//传入的sql语句
List list=new ArrayList();
int index=1;
list.add(index++, user.getId());
list.add(index++, user.getLoginName());
list.add(index++, user.getPwd());//参数设置
return this.executeUpdate(sql, list.toArray());
//调用通用增删查方法,注意将集合转换为对象数组(参数为数组)
}
@Override
public int deleteUser(int id) {
// 删除对象
String sql="delete from a_user where id=?";
List list=new ArrayList();
int index=1;
list.add(index++, id);
return this.executeUpdate(sql, list.toArray());
}
@Override
public int updateUser(User user) {
// 修改对象
String sql="update a_user set loginName=?, pwd=? where id=?";
List list=new ArrayList();
int index=1;
list.add(index++, user.getLoginName());
list.add(index++, user.getPwd());
list.add(index++, user.getId());
return this.executeUpdate(sql, list.toArray());
}
@Override
public List findCondition(User user) {
//按条件查询
//拼接sql用buffer不用普通字符串,大量浪费字符池内存
List paramList=new ArrayList();
StringBuffer sf=new StringBuffer();
sf.append("select * from a_user where 1=1");
//这个sql语句可以很方便的解决where的问题
if(user!=null){//根据对象是否有值来拼接sql字符串
if(user.getId()>0){
sf.append(" and id=? ");
paramList.add(user.getId());
}
if(user.getLoginName()!=null&&!user.getLoginName().isEmpty()){
sf.append(" and loginName=? ");
paramList.add(user.getLoginName());
}
if(user.getPwd()!=null&&!user.getPwd().isEmpty()){
sf.append(" and pwd=? ");
paramList.add(user.getPwd());
}
}
//下面是调用返回值为RS的查询的代码块
// ResultSet rs=this.executeQuery1(sf.toString(), paramList.toArray());
// List list=new ArrayList();
// try
// {
// while(rs.next()){
// User user=new User();
// user.setPassword(rs.getString("password"));
// user.setLoginName(rs.getString("loginName"));
// user.setId(rs.getInt("id"));
// list.add(user);
// }
// } catch (Exception e)
// {
// e.printStackTrace();
// }
return this.executeQuery(sf.toString(), paramList.toArray());//调用查询方法
}
@Override
public Object getEntity(ResultSet rs) {
// 根据传入的rs来获取对象值并返回一个对象,父类方法子类重写,new子类对象调用方法会按照子类对象属性设置
User user=null;
try
{
user=new User();
user.setPwd(rs.getString("pwd"));
user.setLoginName(rs.getString("loginName"));
user.setId(rs.getInt("id"));
} catch (Exception e)
{
e.printStackTrace();
}
return user;//返回对象
}
}
总的来说我理解的这个User案例的过程就是新建接口dao,然后在其中设置抽象方法比如增删改查,然后新建接口的实现类UserDaoImpl,用来实现接口的方法,同时将重复繁琐的代码提升一层封装在一个抽象类BaseDao中,这些方法包括连接数据库的以及释放资源以及增删改的通用代码,然后通过子类实现查询方法也可以封装部分代码,比如查询的那些设置问号值等,除了rs传值给对象是每个实体表不一样其他基本一样可以封装成查询方法,通过传入的sql语句,以及设置问号值的数组,来控制不同的类的代码复用。然后获取对象也是一个子类重写的方法,子类不同返回的对象不同。