Chinaunix首页 | 论坛 | 博客
  • 博客访问: 704695
  • 博文数量: 147
  • 博客积分: 6010
  • 博客等级: 准将
  • 技术积分: 1725
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-22 10:36
文章分类

全部博文(147)

文章存档

2011年(1)

2010年(1)

2009年(35)

2008年(110)

我的朋友

分类: Java

2009-05-10 17:02:41

1.连接数据库的步骤:
  1.注册驱动:
    1.Class.forName("com.mysql.jdbc.Driver");//推荐这种方式
    2.DriverManager.registerDriver(new com.mysql.jdbc.Driver());//会造成DriverManager中产生两个一样的驱动,并会对具体的驱动产生依赖
    3.System.setProperty("jdbc.drivers","driver1:driver2");//很少使用
    驱动的四种类型:
    1.
  2.建立连接(Connection)
    Connection conn=DriverManager.getConnection(url,user,password);
  3.创建执行sql的语句(Statement)
    Statement st=conn.createStatement();
  4.执行语句
    ResultSet rs=st.executeQuery("select * from user");
  5.处理执行结果(ResultSet)
    while(rs.next()){
    ......
    }
  6.释放资源
    rs.close();
    st.close();
    conn.close();
上面的代码只是演示而已,有很多不好的地方
2.下面的方法可以作为模板:
  public final class JdbcUtils{
        //属性
        private static String url="jdbc:mysql://localhost:3306/jdbc";
        private static String user="root";
        private static String password=""
        //私有函数
     private JdbcUtils(){
     }
       //确保驱动只被注册一次
   static{
    try{
           //注册驱动:
          Class.forName("com.mysql.jdbc.Driver");
      }catch(ClassNotFoundException e){
         throw new ExceptionInInitializerError(e);
      }
   }
       //获得连接
       public static Connection getConnection(){
   //建立连接(Connection)
                return DriverManager.getConnection(url,user,password);
 }
 //释放资源
       public static void free(ResultSet rs,Statement st,Connection conn){
  try{
   if(rs!=null)
    rs.close();
  }catch(SQLException e){
   e.printStackTrace();
  }finally{
   try{
    if(st!=null)
       st.close();
   }catch(SQLException e){
    e.printStackTrace(); 
   }finally{
    if(conn!=null)
    try{
     conn.close();
    }catch(SQLException e){
     e.printStackTrance();
    }
   }
  }
 }
  }
Domain对象:
public class User{
....
}
//业务逻辑层接口
public interface UserDao{
public void addUser(User user);
public User getUser(int userId);
public void update(User user);
public void delete(User user);
public User findUser(String loginName,String password);
}
public class DaoException extends RuntimeException{
private static final long serialVersionUID=1L;
public DaoException(){}
public DaoException(String message){
super(message);
}
public DaoException(Throwable cause){
super(cause);
}
public DaoException(String message,Throwable cause){
super(message,cause);
}
}
//实现接口
public class UserDaoJdbcImpl implements UserDao{
public void addUser(User user){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try{
//建立连接
conn=JdbcUtils.getConnection();
String sql="insert into user(name,birthday,money) vlaues(?,?,?)";
ps=conn.preparedStatement(sql);
ps.setString(1,user.getName());
ps.setDate(2,new java.sql.Date(user.getBirthday().getTime()));
ps.setFloat(3,user.getMoney);
ps.executeUpdate();
}catch(SQLException e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
}
public User getUser(int userId){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
User user=null;
try{
//建立连接
conn=JdbcUtils.getConnection();
String sql="select id,name,birthday,money from user where id=?";
ps=conn.preparedStatement(sql);
ps.setInt(1,userId);
rs=ps.executeQuery();
while(rs.next()){
user=mappingUser(rs);
}
}catch(SQLException e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
return user;
}
public void update(User user){
Connection conn=null;
PrepareStatement ps=null;
ResultSet rs=null;
try{
//建立连接
conn=JdbcUtils.getConnection();
String sql="update user set name=?,money=? where id=?";
ps=conn.createStatement(sql);
ps.setString(1,use.getName());
ps.setFloat(2,user.getFloat());
ps.setInt(3,user.getId());
ps.executeUpdate();
}catch(SQLException e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
}
public void delete(User user){
Connection conn=null;
Statement ps=null;
ResultSet rs=null;
try{
//建立连接
conn=JdbcUtils.getConnection();
ps=conn.createStatement(sql);
String sql="delete from user where id="+user.gerId();
ps.executeUpdate(sql);
}catch(SQLException e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
}
public User findUser(String loginName,String password){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
User user=null;
try{
//建立连接
conn=JdbcUtils.getConnection();
String sql="select id,name,birthday,money from user where name=? and password=?";
ps=conn.preparedStatement(sql);
ps.setString(1,loginName);
ps.setString(2,password);
rs=ps.executeQuery();
while(rs.next()){
user=mappingUser(rs);
}
}catch(SQLException e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
return user;
}
private User mappingUser(Result rs) throws SQLException{
User user=new User();
user.setId(rs.getId("id"));
...
return user;
}
}
那么使用如下:UserDao userDao=new UserDaoJdbcImpl();
那么我们还是依赖了实现类UserDaoJdbcImpl,怎么不依赖呢??如下:
daoconfig.properties文件:
userDaoClass=cn.itcast.jdbc.dao.impl.UserDaoJdbcImpl;
public class DaoFactory{
//DaoFactory.getInstance()方法执行时候,首先会对静态的代码块和属性进行初始化,所以userDao要在instance前面定义,否则userDao为null
private static UserDao userDao=null;
private static DaoFactory instance=new DaoFactory();
private DaoFactory(){
try{
Properties prop=new Properties();
InputStream inStream=DaoFactory.class.getClassLoader().getResourceAsStream("daoconfig.properties");//文件放在classpath下面
prop.load(inStream);
String userDaoClass=prop.getProperty("userDaoClass");
userDao=Class.forName(userDaoClass).newInstance();
}catch(IOException e){
 throw new ExceptionInInitializeError(e);
}
}
pubic static DaoFactory getInstance(){
return instance;
}
public UserDao getUserDao(){
return userDao;
}
}
那么使用如下:UserDao userDao=DaoFactory.getInstance().getUserDao();

3.解决statement的sql注入问题
例如:sql="select id,name from user where name='"+name+"'";
如果那么name="' or 1 or '"
则sql=select id,name from user where name='' or 1 or '';
这样就会选择出所有的user了。
那么我们就不能用statement了,可以用preparedstatement语句进行预处理
sql="select id,name from user where name=?";
ps=conn.prepareStatement(sql);
ps.setString(1,"wuxiaoxiao");
rs=ps.executeQuery();
我们还可以测试sql语句执行的时间:
pulic static void main(String args[]){
long start=System.currentTimeMillis();
read("name");
long end=System.currentTimeMillis();
System.out.println(end-start);
}
建议大家使用preparedStatement
4.jdbc的日期类型
  java.sql.date(只有日期没有时间)继承java.util.date(日期和时间都有)
  插入日期:
  sql="insert into user(name,birthday)values(?,?)";
  ps=conn.prepareStatement(sql);
  ps.setString(1,name);
  ps.setDate(2,new java.sql.Date(birthday.getTime()));//birthday是util包中的,而setDate()方法是sql包中的,这样插入的日期就不含时间了
  ps.executeUpdate();//执行不带参数的方法
  读取日期:
  birthday=rs.getDate("birthday");//将sql中的date赋值给util中的date
  这种都是插入日期但是没有时间,如果要插入日期和时间,那么参考我的bllog
5.jdbc操作大文本数据(text)
  插入:
  sql="insert into clob_test(big_text)values(?)";
  ps=conn.prepareStatement(sql);
  File file=new File("src/cn/itcast/jdbc/JdbcUtils.java");
  Reader reader=new BufferedReader(new FileReader(file)); 
  ps.setCharacterStream(1,reader,(int)file.length());
  //ps.setString(1,x);
  ps.executeUpdate();
  reader.close();
  读取:
  Reader reader=rs.getCharacterStream(1);
 //String dfjkd=rs.getString(1);
  File file=new File("JdbcUtils_bak.java");
  Writer writer=new BufferedWriter(new FileWriter(file));
  Char[] buff=new char[1024];
  for(int i=0;(i=reader.read(buff))>0;){
    writer.write(buff,o,i);
  }
  writer.close();
  reader.close();
6.访问二进制数据(blob(64k),bigblob)
  插入:
  sql="insert into blob_test(big_text)values(?)";
  ps=conn.prepareStatement(sql);
  File file=new File("src/cn/itcast/jdbc/JdbcUtils.jpg");
  InputStream in=new BufferedInputStream(new FileInputStream(file)); 
  ps.setBinaryStream(1,in,(int)file.length()); 
  ps.executeUpdate();
  in.close();
  读取:
  Blob blob=rs.getBlob(1);
  InputStream in=blob.getBinaryStream(); 
  File file=new File("JdbcUtils_bak.jpg");
  OutputStream out=new BufferedOutputStream(new FileOutputStream(file));
  Byte[] buff=new Byte[1024];
  for(int i=0;(i=in.read(buff))>0;){
    out.write(buff,o,i);
  }
  out.close();
  in.close();
7.事务
 try{
  conn=.....
  conn.setAutoCommit(false);//开启事务
  .........
  SavePoint sp=conn.setSavePoint();
  .......
  conn.commit();//提交事务
 }catch(RuntimeException e){
  if(conn!=null&&sp!=null)
   {  co

nn.callback(sp);//回滚事务
      conn.commit();
   }
  throw e;

  }catch(SQLException e){
  if(conn!=null)
     conn.callback();//回滚事务
  throw e;
  }
}
8.JTA
如果事务跨越多个数据源,使用JTA容器(WebLogic等)实现事务
分成两阶段提交:
第一阶段给所有的数据库发送提交的请求,如果有数据库要回滚,那么通知其他的数据库都回滚,如果没有数据库要回滚,那么在发第二条命令提交
这些操作需要JTA容器来指挥。
9.事务隔离级别:
  conn=....
  conn.setAutoCommit(false);
  conn.setTransactionlsolation(Connection.TRANSACTION_READ_COMMITED);//设置事务隔离级别
10.使用jdbc调用存储过程
  CallableStatement(从PreperedStatement扩展而来)
  cs=connection.prepareCall("{call psname(?,?,?,?)}");
  cs.registerOutParameter(4,Type.INTEGER);//存储过程中第四个参数是输出参数
  cs.setString(1,"ps name");
  cs.setDate(2,new java.sql.Date(System.currentTimeMillis()));
  cs.setFloat(3,100f);
  cs.executeUpdate();
  int id=cs.getInt(4);//获得存储过程的输出结果
  拿取主键方法:
  ps=conn.prepareStatement(sql,Statement.RETURN_GENERTED_KEYS);
  ps.executeUpdate();
  rs=ps.getGeneratedKeys(); 
  int id=0;
  if(rs.next())
    id=rs.getInt(1);
  return id; 
 
  获得use的id,可以确保保存前后user不一样:
 public void addUser(User user){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try{
//建立连接
conn=JdbcUtils.getConnection();
String sql="insert into user(name,birthday,money) vlaues(?,?,?)";
ps=conn.preparedStatement(sql,Statement.RETURN_GENERTED_KEYS);
ps.setString(1,user.getName());
ps.setDate(2,new java.sql.Date(user.getBirthday().getTime()));
ps.setFloat(3,user.getMoney);
ps.executeUpdate();
 rs=ps.getGeneratedKeys();  
  if(rs.next())
    user.setId(rs.getInt(1));
}catch(SQLException e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
}
11.jdbc批处理功能
public void addUser(User user){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try{
//建立连接
conn=JdbcUtils.getConnection();
String sql="insert into user(name,birthday,money) vlaues(?,?,?)";
ps=conn.preparedStatement(sql,Statement.RETURN_GENERTED_KEYS);
for(int i=0;i<1000;i++){
ps.setString(1,user.getName());
ps.setDate(2,new java.sql.Date(user.getBirthday().getTime()));
ps.setFloat(3,user.getMoney);
ps.addBatch();
}
int[] is=ps.executeBatch();
  
}catch(SQLException e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
}
12.可滚动的结果集
按照jdbc的规范,创建可滚动的结果集:
st=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);//既可以向前滚,也可以向后滚,只读的
st.next();st.previous();st.absolute(5);
分页:
sql="select id,name from user limit 150,10";//mysql特有的关键字limit,从第150开始去10条记录
可更新的结果集:
st=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE(可滚动的,能感知数据库的变化),ResultSet.CONCUR_UPDATABLE);//既可以向前滚,也可以向后滚,只读的
rs=st.executeQuery(sql);
while(rs.next()){
String name=rs.getString("name");
if("lisi".equals(name)){
rs.updateFloat("money",300f);
rs.updateRow();
}
}
13.数据库的元数据信息:
这样知道数据库支持不支持一些jdbc规范呢?
DatabaseMetaData dbmd=conn.getMetaData();
System.out.println(dbmd.getDataBaseProductName());
.......
conn.close();
14.参数元数据
public void read(String sql(是有占位符的),Object[]  params){
.....
ps=conn.prepareStatement(sql);
ParameterMetaData pmd=ps.getPatameterMetaData();
int count=pmd.getParameterCount();//获得参数的个数
for(int i=1;i<=count;i++){
//System.out.pritnln(pmd.getParameterClassName(i));
//System.out.pritln(pmd.getParameterType(i));
//System.out.pritln(pmd.getParameterTypeName(i));
ps.setObject(i,params[i-1]);
}
rs=ps.executeQuery();
}
14.利用结果集元数据将查询结果封装为map
public Map read(String sql){//返回结果一个
.....
ResultSetmetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
String[] colNames=new String[count];
for(int i=1;i<=count;i++){
 //System.out.println(rsmd.getColumnClassName(i));
colNames[i-1]=rsmd.getColumnName(i);
}
Map data=null;
if(rs.next()){
data=new HashMap();
for(int i=0;idata.put(colNames[i],rs.getObject(colNames[i]));
}
}
}

public List> read(String sql){//返回很多结果
.....
ResultSetmetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
String[] colNames=new String[count];
for(int i=1;i<=count;i++){
 //System.out.println(rsmd.getColumnClassName(i));
colNames[i-1]=rsmd.getColumnName(i);
}
List> datas=new ArrayList>();
while(rs.next()){
Map data=new HashMap();
for(int i=0;idata.put(colNames[i],rs.getObject(colNames[i]));
}
datas.add(data);
}
return datas;
}
15.java反射技术:
传递一个class,给我构造一个对象
通过clazz.newInstance()方法构造一个对象,这个类必须有一个没有参数的构造方法
如果构造方法都有参数的话,就这样:
public class User{
private int id;
...
public User(){}
public User(String name){
this.name=name
}
public User(Float money){
....
}
.......
}
//构造对象的方法(只要类中含有参数为String类型的构造方法)
public Object create(Class clazz){
Constructor con=clazz.getConstructor(String.class);//获得带有参数为String类型的构造方法
Object obj=con.newInstance("test name");
}
//获得一个类的方法
public void invoke1(Object obj,String methodName){
Method[] ms=obj.getClass().getDeclaredMethods();//获得obj的所有方法(构造方法除外,私有的方法也能找出来,超类的方法没有)
Method[] ms=obj.getClass().getMethods();//获得obj的所有方法(构造方法除外,私有的方法找不到,超类的方法能找到,静态方法能找到)
for(Method m:ms){
  System.out.println(m.getName());//输出方法名
  if(methodName.equals(m.getName()));
     m.invoke(obj,null(方法的参数));//调用方法
}
//Method m=obj.getClass().getMethod(methodName,null(方法的参数));//精确定位一个方法
}
//获得类定义的属性
public field(Class clazz){
Field[] fs=clazz.getDeclaredFilelds();//私有的也能找到
fs=class.getFields();//私有的找不到
for(Field f:fs)
  System.out.pritnln(f.getName());
}
16.利用反射技术将查询结果封装为对象
public Object getObject(String sql,Class clazz){
.....
ResultSetmetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
String[] colNames=new String[count];
for(int i=1;i<=count;i++){
 //System.out.println(rsmd.getColumnClassName(i));
colNames[i-1]=rsmd.getColumnLabel(i);
}
Object object=null;
if(rs.next()){
object=clazz.newInstance();//clazz必须有一个不带参数的构造方法
for(int i=0;iString colName=colNames[i]//假设列明和属性名一样
String methodName="set"+colName;//这里sql应该为“select id as Id,name as Name from user where id=1”
Method[] ms=clazz.getClass().getMethods();
for(Method m:ms){
if(methodName.equals(m.getName())){
m.invoke(user,rs.getObject(colName));
}
}
}
}
return object;
}
17.数据库连接池来实现连接的复用:
public class MyConnection implements java.sql.Connection{
private java.sql.Connection realConnection;
private MyDataSource dataSource;
//private int maxUseCount=10;//最大的使用次数
//private int currentUseCount=0;//当前使用的次数
MyConnection(java.sql.Connection Connection,MyDataSource dataSource){
 this.realConnection=connection;
 this.dataSource=dataSource;
}
public void clearWarnings()throws SQLException{
this.realConnection.clearWarnings();
}
public void close() throws SQLException{
//this.currentUseCount++;
//if(this.currentUseCount this.dataSource.connectionPool.addLast(this);
//else{
// this.realConnection.close();
// this.dataSource.currentCount--;
//}
}
public void commit() throws SQLException{
this.realConnection.commit()
}
//其他的方法都是调用realConnection的方法,我们关心close方法
.....
}

public class MyDataSource{
private static String url="...";
private static String user="...";
private static String password="...";
private static int initCount=10;//初始化连接数
private static maxCount=100;//最大连接数
private int currentCount=0;//当前创建的连接数
//ArrayList访问速度快 LinkedList增加和删除速度快
private LinkedList connectionPool=new LinkedList();
//初始化10个连接
public MyDataSource(){
try{
 for(int i=0;i   this.connectionPool.addLast(this.createConnection());
   currentCount++;
 }
}catch(SQLException e){
  throw new ExceptionInInitializerError(e);
}
}
//获取连接
public Connection getConnection() throws SQLException{
//确保线程拿的不是同一个连接
synchronized(connectionPool){
 if(this.connectionPool.size()>0)
    return this.connectionPool.removeFirst();
 if(this.currentCount   this.currentCount++;
   return this.createConnection();
 }
 throw new SQLException("已经没有连接");
}
}
//释放连接
public void free(Connection conn){
this.connectionPool.addLast(conn);
}
//创建连接
private Connection createConnection() throws SQLException{
Connection realConn=DriverManager.getConnection(url,user,password);
MyConnection myConnection=new MyConnection(realConn,this);
return myConnection;
}
}
}
public final class JdbcUtils{
        private MyDataSource myDataSource=null;
        //私有函数
     private JdbcUtils(){
     }
       //确保驱动只被注册一次
   static{
    try{
           //注册驱动:
          Class.forName("com.mysql.jdbc.Driver");
                         myDataSource=new MyDataSource();
      }catch(ClassNotFoundException e){
         throw new ExceptionInInitializerError(e);
      }
   }
       //获得连接
       public static Connection getConnection(){
   //建立连接(Connection)
                return myDataSource.getConnection();
 }
 //释放资源
       public static void free(ResultSet rs,Statement st,Connection conn){
  try{
   if(rs!=null)
    rs.close();
  }catch(SQLException e){
   e.printStackTrace();
  }finally{
   try{
    if(st!=null)
       st.close();
   }catch(SQLException e){
    e.printStackTrace(); 
   }finally{
    if(conn!=null)
    try{
     conn.close();
                                       // myDataSource.free(conn);
    }catch(SQLException e){
     e.printStackTrance();
    }
   }
  }
 }
  }
实际工作中不会让自己写连接池,用的是其他的连接池
//动态代理实现拦截close方法
class MyConnectionHandler implements IncocationHandler{
private Connection realConnection;
private Connection warpedConnection
private MyDataSource dataSource;
MyConnectionHandler(MyDataSource dataSource){
this.dataSource=dataSource;
}
java.sql.Connection bind(java.sql.Connection realConn){
this.realConnection=realConn;
this.warpedConnection=(Connection)Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{Connection.class},this);
return warpedConnection;
}
public Object invoke(Object proxy, Method method,Object[] args) throws Throwable{
if("close".equals(method.getName())){
this.dataSource.connectionsPool.addLast(this.warpedConnection);
}
return method.invoke(this.realConnection,args);
}

使用
createConnection(){
Connection realConn=DriverManager.getConnection(..........);
MyConnectionHandler proxy=new MyConnectionHandler(this);
return proxy.bind(realConnection);
}
18.使用开源的数据源---DataSource标准接口取代DriverManager
下面介绍开源的DBCP数据源:
首先配置文件放在classpath下面:
dbcpconfig.properties
#连接设置
driverClassName=....
url=....
username=.....
password=...
#初始化连接数
initialSize=10
#最大连接数
maxActive=50
#最大空闲连接数
maxIdle=20
#最小空闲连接
minIdle=5
#超时等待时间以毫秒为单位 6000毫秒/1000等于60秒
maxWait=60000
#JDBC驱动简历连接时附带的连接属性的格式必须为这样:[属性名=property;]
#注意:“user”与”password“两个属性会被明确的传递,因此这里不需要包含他们
connectionProperties=userUnicode=true;characterEncoding=gbk
#指定有连接池所创建的连接的自动提交状态
defaultAutoCommit=true
#driver default指定由连接池多创建的连接的只读状态
#如果没有设置该值,则setReadOnly方法将不被调用
defaultReadOnly=
#driver default指定由连接池多创建的连接的事务级别
#可用值为下列之一:(NONE,READ_UNCOMMITED,READ_COMMITED,READ_)
defaultTransactionIsolation=READ_UNCOMMITTED
.............
然后加入jar包(commons-collections-3.1.jar,commons-dbcp-1.2.1.jar,commons-pool.jar)
public final class JdbcUtils{
        private DataSource myDataSource=null;
        //私有函数
     private JdbcUtils(){
     }
       //确保驱动只被注册一次
   static{
    try{             
                         Properties prop=new Properties();
                         InputStream is=JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
                         prop.load(is);                       
                         myDataSource=BasicDataSourceFactory.createDataSource(prop);
      }catch(ClassNotFoundException e){
         throw new ExceptionInInitializerError(e);
      }
   }
       //获得连接
       public static Connection getConnection(){
   //建立连接(Connection)
                return myDataSource.getConnection();
 }
 //释放资源
       public static void free(ResultSet rs,Statement st,Connection conn){
  try{
   if(rs!=null)
    rs.close();
  }catch(SQLException e){
   e.printStackTrace();
  }finally{
   try{
    if(st!=null)
       st.close();
   }catch(SQLException e){
    e.printStackTrace(); 
   }finally{
    if(conn!=null)
    try{
     conn.close();                                      
    }catch(SQLException e){
     e.printStackTrance();
    }
   }
  }
 }
  }
19.优化DAO的方法:
抽象类:
public abstract class AbstractDao{
更新方法
public int update(String sql,Object[] args){
Connection conn=null;
PrepareStatement ps=null;
ResultSet rs=null;
try{
conn=JdbcUtils.getConnection();
ps=conn.prepareStatement(sql);
for(int i=0;i  ps.setObject(i+1,args[i]);
return ps.executeUpdate();
}catch(Exception e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
}
查询方法
public Object find(String sql,Object[] args){
Connection conn=null;
PrepareStatement ps=null;
ResultSet rs=null;
try{
conn=JdbcUtils.getConnection();
ps=conn.prepareStatement(sql);
for(int i=0;i  ps.setObject(i+1,args[i]);
ps.executeUpdate();
Object obj=null;
if(rs.next()){
   obj=rowMapper(rs);
}
return obj;
}catch(Exception e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
}
//抽象方法,让子类去做
abstract protected Object rowMapper(ResultSet rs) throws SQLException;
}
public class UserDaoImpl extends AbstractDao{
public void update(User user){
String sql="update user set name=?,birthday=? where id=?";
Object args=new Object[]{user.getName(),user.getBirthday(),user.getId()};
super.update(sql,args);
}
public void delete(User user){
String sql="delete from user where id=?";
Object[] args=new Object[]{user.getId()};
super.update(sql,args);
}
//不获得主键,要是获得主键easy
public void add(User user){
String sql="insert into user(name,birthday) vlaues(?,?)";
Object[] args=new Object[]{user.getName(),user.getBirthday()};
super.update(sql,args);
}
//查询
public User findUser(String loginName,String password){
String sql="select id,name,birthday from user where name=?";
Object[] args=new Object[]{loginName};
Object obj=super.find(sql,args);
return (User)obj;
}
protected Object rowMapper(ResultSet rs)throws SQLException{
User user=new User();
user.setId();
...
return user;
}
那么如果要查询public String findUserName(int id)怎么办呢????那么用继承的方式不是很灵活!
}
下面重新来做:
抽象类
public class MyDaoTemplate{
查询方法
public Object find(String sql,Object[] args,Rowmapper rowMapper){
Connection conn=null;
PrepareStatement ps=null;
ResultSet rs=null;
try{
conn=JdbcUtils.getConnection();
ps=conn.prepareStatement(sql);
for(int i=0;i  ps.setObject(i+1,args[i]);
ps.executeUpdate();
Object obj=null;
if(rs.next()){
   obj=rowMapper.mapRow(rs);
}
return obj;
}catch(Exception e){
throw new DaoException(e.getMessage(),e);
}finally{
JdbcUtils.free(rs,ps,conn);
}
}
}
映射接口
public interface RowMapper{
pblic Object mapRow(ResultSet rs);
}
//dao类
public class UserDaoImpl{
MyDaoTemplate template=new MyDaoTemplate();
public User findUser(String loginName,String password){
String sql="select id,name,birthday from user where name=?";
Object[] args=new Object[]{loginName};
Object user=this.template.find(sql,args,new RowMapper(){
public Object mapRow(ResultSet rs)throws SQLException{
User user=new User();
user.setId(rs.getInt("id"));
.....
return user;
}
});
return (User)user;
}
public User findUserName(int id){
String sql="select name from user where name=?";
Object[] args=new Object[]{id};
Object user=this.template.find(sql,args,new RowMapper(){
public Object mapRow(ResultSet rs) throws SQLException{
 return rs.getString("name");
}
});
return ((User)user).getName();
}
}
20.使用JdbcTemplate根据简化查询:
spring框架中提供了一个JdbcTemplate工具类,JdbcTemplate类对Jdbc API进行了很好的封装这个类就像我们自己对JDBC进行封装一样,以后我们可使用JdbcTemplate类来完全替代直接使用Jdbc api,这与直接使用JDBC API没有太大的性能区别使用JDBCTemplate类需要额外从spring开发包中导入spring.jar和commons-logging.jar包
public final class JdbcUtils{
        private DataSource myDataSource=null;
        //私有函数
     private JdbcUtils(){
     }
       //确保驱动只被注册一次
   static{
    try{             
                         Properties prop=new Properties();
                         InputStream is=JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
                         prop.load(is);                       
                         myDataSource=BasicDataSourceFactory.createDataSource(prop);
      }catch(ClassNotFoundException e){
         throw new ExceptionInInitializerError(e);
      }
   }
       //获得数据源
       public static DataSource getDataSource(){
            return myDataSource;
       }
       //获得连接
       public static Connection getConnection(){
   //建立连接(Connection)
                return myDataSource.getConnection();
 }
 //释放资源
       public static void free(ResultSet rs,Statement st,Connection conn){
  try{
   if(rs!=null)
    rs.close();
  }catch(SQLException e){
   e.printStackTrace();
  }finally{
   try{
    if(st!=null)
       st.close();
   }catch(SQLException e){
    e.printStackTrace(); 
   }finally{
    if(conn!=null)
    try{
     conn.close();                                      
    }catch(SQLException e){
     e.printStackTrance();
    }
   }
  }
 }
  }
JdbcTemplate模板:
public class UserDaoImpl{
//查询
public User findUser(String name){
JdbcTemplate jdbc=new JdbcTemplate(JdbcUtils.getDataSource());
String sql="select id,name,birthday from user where name=?";
Object[] args=new Object[]{name};
jdbc.queryForObject(sql,args,new RowMapper(){//queryForObject返回一个结果,如果返回多个会报错
public Object mapRow(ResultSet rs,int rowNum) throws SQLException{
User user=new User();
.....
return user;
}
});
return (User)user;
}
或者:
//查询
public User findUser(String name){
JdbcTemplate jdbc=new JdbcTemplate(JdbcUtils.getDataSource());
String sql="select id,name,birthday from user where name=?";
Object[] args=new Object[]{name};
Object user=jdbc.queryForObject(sql,args,new BeanPropertyRowMapper(User.class));
return (User)user;
}
//返回列表
public List findUsers(int id){
JdbcTemplate jdbc=new JdbcTemplate(JdbcUtils.getDataSource());
String sql="select id,name,birthday from user where idObject[] args=new Object[]{id};
List users=jdbc.query(sql,args,new BeanPropertyRowMapper(User.class));//query返回多个结果
return users;
}
//查看多少个
public int getUserCount(){
JdbcTemplate jdbc=new JdbcTemplate(JdbcUtils.getDataSource());
String sql="select count(*) from user";
return jdbc.queryForInt(sql);//queryForInt返回整形数值
}
//查询用户的名字
public String getUserName(int id){
JdbcTemplate jdbc=new JdbcTemplate(JdbcUtils.getDataSource());
String sql="select name from user where id="+id;
Object name=jdbc.queryForObject(sql,String.class);//返回string类型
return (String)name;
}
//返回Map
public Map getData(int id){
JdbcTemplate jdbc=new JdbcTemplate(JdbcUtils.getDataSource());
String sql="select id,name,birthday from user where id="id;
return jdbc.queryForMap(sql);//查询结果放在Map里面(key是别名或者列明,值是对应的列值)
//queryForList返回的是list,里面的元素是Map
}
//更新
......
public int addUser(fianl User user){
JdbcTemplate jdbc=new JdbcTemplate(JdbcUtils.getDataSource());
jdbc.execute(new ConnectionCallback(){//回调连接
public Object doInConnection(Connection con)throws SQLException,DataAccessException{
String sql="insert into......";
PreparedStatement ps=conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
ps.setString(1,user.getName());
...
ps.executeUpdate();
ResultSet rs=ps.getGeneratedKeys();
if(rs.next())
   user.setId(rs.getInt("id"));
return null;
}
});
return 0;
}
}
21.使用支持命名参数的JdbcTemplate
22.使用SimpleJdbcTemplate和泛型技术简化代码
public User getUser(String name){//public T find(String name,Class clazz)
SimpleJdbcTemplate simple=new SimpleJdbcTemplate(JdbcUtils.getDataSource());
String sql="select id,name,birthday from user where name=? and money=?";
Object user=simple.queryForObject(sql,ParameterizedBeanPropertyRowMapper.newInstance(User.class),name,100f);//传递参数不受限制
return (User)user;
}
23.使用JdbcTemplate实现DAO和用工厂灵活切换实现
//使用SimpleTemplate
public  class UserDaoSpringImpl implements UserDao{
SimpleJdbcTemplate simple=new SimpleJdbcTemplate(JdbcUtils.getDataSource());
//增加
public void addUser(User user){
String sql="insert into user(name.birthday) vlaues(:name,:birthday)";
SqlParameterSource param=new BeanPropertySqlParameterSource(user);
KeyHolder keyHolder=new GeneratedKeyHolder();
this.simpleJdbcTemplate.getNamedParameterJdbcOperations().update(sql,param,keyHolder);
user.setId(keyHolder.getKey().initValue());
}
//删除
public void delete(User user){
String sql="delete from user where id=?";
this.simpleJdbcTemplate.update(sql,user.getId());
}
//查询
publci User findUser(String loginName,String password){
String sql="select id,name from user where name=?";
return this.simpleJdbcTemplate.queryForObject(sql,ParameterizedBanPropertyRowMapper.newInstance(User.class),loginName);
}
//查询
publci User getUser(int userId){
String sql="select id,name from user where id=?";
return this.simpleJdbcTemplate.queryForObject(sql,ParameterizedBanPropertyRowMapper.newInstance(User.class),userId);
}
//更新
public void update(User user){
String sql="update user set name=?,birthday=? where id=?";
this.simpleJdbcTemplate.update(sql,user.getName(),use.getBirthday(),user.getId())
//或者
String sql="update user set name=:name,birthday=:birthday where id=:id";
this.simpleJdbcTemplate.update(sql,new BeanPropertySqlParameterSource(user));//BeanPropertySqlParameterSource方法中的:id必须和类的属性名一样
}
}
阅读(2318) | 评论(0) | 转发(0) |
0

上一篇:SimpleJdbcTemplate模板

下一篇:Ajax视频学习

给主人留下些什么吧!~~