继承法相比封装法更加精炼。
-
写一个BaseDao类,所有Dao层都继承这个BaseDao。
BaseDao要实现什么功能:
获取连接
产生执行sql语句的对象
使用sql对表操作 -
获取连接,即读取jdbc.properties文件
读取文件操作每次调用方法都要执行一次可以写在static方法。
private static String jdbcDriver= "";
private static String jdbcURL="";
private static String jdbcUser="";
private static String jdbcPassword="";
//静态初始化块只会在类加载的时候执行一次
static {
//读取jdbc.properties文件
InputStream is=BaseDao.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties p=new Properties();
try {
p.load(is);
jdbcDriver =p.getProperty("jdbDriver");
jdbcURL=p.getProperty("jdbcURL");
jdbcUser=p.getProperty("jdbcUser");
jdbcPassword=p.getProperty("jdbcPassword");
} catch (IOException e) {
e.printStackTrace();
}
}
获取连接方法和关闭方法
protected Connection conn=null;
protected PreparedStatement ps = null;
这俩个都需要使用的方法可以提出方法之外
protected 包内部可以调用
protected Connection conn=null;
protected PreparedStatement ps = null;
//创建
public Connection getConnection(){
//获取连接
//Connection conn=null;
//产生执行sql语句的对象
//PreparedStatement ps=null;
//加载驱动
try {
Class.forName(jdbcDriver);
conn= DriverManager.getConnection(jdbcURL,jdbcUser,jdbcPassword);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//关闭
public void closeAll(ResultSet rs, PreparedStatement ps, Connection conn){
//关闭资源,先产生的后关闭
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
if(ps !=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
if (conn !=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
}
增删改查方法
增删改查中查询和其他方法不同
添加、修改、删除的属于改变表信息只是sql语句和输入内容不同可以写成一个语句
//Object... 表示该方法可以接受0个或者多个任意类型的参数
protected int executeUpdate(String sql,Object... params){
int result=0;
try {
conn= this.getConnection();
ps=conn.prepareStatement(sql);
for (int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);
}
result= ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
this.closeAll(null,ps,conn);
}
return result;
}
查询操作需要给ResultSet赋值,但表数据和对象不同值也不同。在方法里不好用。外面赋值也无法关闭连接,所有这些操作在方法外写
protected ResultSet executeQuery(String sql,Object... params){
ResultSet rs=null;
try {
conn=this.getConnection();
ps=conn.prepareStatement(sql);
for (int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);
}
rs=ps.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
来看其子类如果使用
先基础BaseDao
public class UserDaoImpl extends BaseDao implements UserDao
修改操作比较简单把sql及对象参数填上
@Override
public int deleteUserById(int userId) {
String sql="DELETE FROM user WHERE userId=?";
return this.executeUpdate( sql,userId);
}
@Override
public int saveUser(User user) {
String sql ="insert into user(username,password) values (?,?)";
return this.executeUpdate(sql,user.getUsername(),user.getPassword());
}
@Override
public int updateByUserId(User user) {
String sql ="UPDATE user set password=? where userId=?";
return this.executeUpdate(sql,user.getPassword(),user.getUserId());
}
查询就比较复杂些了
ResultSet和关闭操作都要写
@Override
public User getUserByUsernameAndPassword(String username, String password) {
User user =null;
ResultSet rs = null;
String sql = "SELECT * FROM user WHERE username=? AND password=?";
rs =this.executeQuery(sql,username,password);
try {
if (rs.next()) {
user = new User();
user.setUserId(rs.getInt("userId"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
this.closeAll(rs,ps,conn);
}
return user;
}
总体来说,在没有用框架的情况下,这样写还是很方便的。