Class.forName(config.getProperty("driver"));
} catch (Exception e) {
// 直接报错,因为配置文件有问题,连接不了数据库
throw new ExceptionInInitializerError(e);
}
}
// 提供一个静态方法,为程序提供连接,异常直接抛给调用程序处理
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(config.getProperty("url"), config.getProperty("user"), config.getProperty("password"));
}
// 提供一个释放资源的方法
public static void release(Connection conn, Statement st, ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (Exception e) {
// 记录下异常信息
e.printStackTrace();
rs = null;
}
}
if(st!=null){
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
st = null;
}
}
if(conn!=null){
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
conn = null;
}
}
}
}
db.properties文件{
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
user=root
password=root
}
工厂类:将程序与dao层的操作进行解耦,{
//在web程序中,该工厂实现了service和dao层解耦。在修改底层代码的时候,不需要修改上层的代码,只需要修改配置文件即可
public class DaoFactory {
// 读取配置文件来创建接口对应的dao实例,也可以将该代码放在构造函数中
private static Properties prop = new Properties();
static{
try {
// dao.properties文件内 包含: UserDao = cn.halm.dao.UserDaoImpl
prop.load(DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//需要设计为单例模式
// 1.构造函数私有化
private DaoFactory() {}
// 2.创建该类的一个私有的实例化对象
private static DaoFactory instance = new DaoFactory();
// 3.将该对象提供给程序
public static DaoFactory getInstance(){
return instance;
}
// 提供一个方法,从配置文件中读取信息后根据接口创建相应的实现类实例
public T createDao(Class interfaceClazz){
try {
// 通过接口字节码文件获取接口名
String interfaceName = interfaceClazz.getSimpleName();
// 通过接口名获取配置文件中对应的该接口的实现类的名称
String implName = prop.getProperty(interfaceName);
// 返回该实现类的实例
return (T) Class.forName(implName).newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
PreparedStatement对象{
1.是Statement的子类
2.可以有效的防止SQL注入:
sql = "select * from users where username = '"+username+"' and password = '"+password+"'";如果两个变量password,username="'or 1=1 or username='",那么该语句就为:select * from users where username='' or true or username=''——>select * from users where true;该语句就一定能从数据库中找到数据。这就是SQL注入!如果使用PreparedStatement会对传入的变量进行转义,就能预防该问题
3.该对象会对sql语句进行预编译,以减轻数据库服务器的压力,提高效率。statement对象会使数据库频繁编译sql,可能造成数据库缓冲区溢出
4.允许使用占位符替换参数,简化sql语句的编写
用法:
// 定义sql语句,包含占位符“?”
String sql = "select * from users where username= and id= ";
// 预编译sql语句获取对象
PreparedStatement st = conn1.prepareStatement(sql);
// 从1开始,不同类型的数据使用不同的方法
st.setString(1, user.getUsername());
st.setInt(2, user.getId());
st.executeQuery();
// st.executeUpdate();insert,update,delete语句使用
获取插入数据的主键值:getGeneratedKeys()获取新插入数据的在数据库中自动增长的值,一般为主键{
如果没有这个方法,如果该主键值在数据库中被设置为自动增长,插入数据就不需要传入主键值,所以就无法直接获取该主键值,必须通过查表
注意:在mysql数据库中只能有一个字段修饰为auto_increment
// 获取执行执行sql语句的对象,指定一个常量值Statement.RETURN_GENERATED_KEYS,说明该自动增长的主键值被返回,如果不是insert的sql可以忽略该参数值,没有该参数,就不返回主键值