DAO包规范
domain:存储所有的domain
dao:存储所有的dao接口
dao.impl:存储所有的Dao接口实现类
dao.test:存储Dao组件的测试类
没有预编译语句时,所有的sql都是进行拼接,复杂且不安全。
预编译语句:
PreparedStatement 用于预编译模板SQL语句
在性能和代码灵活性上有显著地提高
PreparedStatement 对象使用 ? 作为占位符,即参数标记;
使用setXXX( index,value) 方法将值绑定到参数中,每个参数标记是其顺序位置引用,注意 index 从 1 开始;
为什么PrepareState就能够防sql注入
之所以PreparedStatement能防止注入,是因为它把单引号转义了,变成了\',这样一来,就无法截断SQL语句,进而无法拼接SQL语句 基本上没有办法注入了。
将连接数据库提取为一个单独的工具类,放在util包中:(util/JdbcUtil.java)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcUtil {
public static String driverClassName="com.mysql.jdbc.Driver";
public static String url="jdbc:mysql://localhost:3306/test03?rewriteBatchedStatements=true";
public static String username="root";
public static String password="123456";
static {
try {
Class.forName(driverClassName);
}catch(Exception e) {
e.printStackTrace();
}
}
public static Connection getConn() {
try {
// 2.连接数据
return DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 关闭资源
*/
public static void close(Connection conn,Statement st,ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
假设存在表格Student
目录结构如下:
Student.java
public class Student {
Integer id;
String name;
Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
IStudentDao.java
import java.util.List;
import domain.Student;
public interface IStudentDao {
/**
*保存一个学生
*/
public void save(Student stu);
/**
*删除学生
*/
public void delete(int id);
/**
*更新一个学生信息
*/
public void update(int id,Student stu);
/**
*获取指定学生
*/
public Student get(int id);
/**
*获取所有的学生
*/
public List<Student> getAll();
}
StudentDaoImpl
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import dao.IStudentDao;
import domain.Student;
import util.JdbcUtil;
public class StudentDaoImpl implements IStudentDao {
@Override
public void save(Student stu) {
Connection conn = null;
PreparedStatement ps = null;
try {
// 1.加载驱动
// 2.连接数据库
conn = JdbcUtil.getConn();
// 3.创建语句
String sql = "insert into student(name,age) values(?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, stu.getName());
ps.setInt(2, stu.getAge());
// 4.执行语句
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 5.释放资源
JdbcUtil.close(conn, ps, null);
}
}
@Override
public void delete(int id) {
Connection conn = null;
PreparedStatement ps = null;
try {
// 1.加载驱动
// 2.连接数据库
conn = JdbcUtil.getConn();
// 3.创建语句
String sql = "delete from student where id = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
// 4.执行语句
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 5.释放资源
JdbcUtil.close(conn, ps, null);
}
}
@Override
public void update(int id, Student stu) {
Connection conn = null;
PreparedStatement ps = null;
try {
// 1.加载驱动
// 2.连接数据库
conn = JdbcUtil.getConn();
// 3.创建语句
String sql = "update student set name=?, age=? where id =? ";
ps = conn.prepareStatement(sql);
ps.setString(1, stu.getName());
ps.setInt(2, stu.getAge());
ps.setInt(3, id);
// 4.执行语句
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(conn, ps, null);
}
}
@Override
public Student get(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1.加载驱动
// 2.连接数据库
conn = JdbcUtil.getConn();
// 3.创建语句
String sql = "select * from student where id = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
// 4.执行语句
rs = ps.executeQuery();
if (rs.next()) {
Student stu = new Student();
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
stu.setId(rs.getInt("id"));
return stu;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 5.释放资源
JdbcUtil.close(conn, ps, rs);
}
return null;
}
@Override
public List<Student> getAll() {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 1.加载驱动
// 2.连接数据库
conn = JdbcUtil.getConn();
// 3.创建语句
st = conn.createStatement();
String sql = "select * from student ";
System.out.println(sql);
// 4.执行语句
rs = st.executeQuery(sql);
//创建一个集合
List<Student> list = new ArrayList<Student>();
while (rs.next()) {
Student stu = new Student();
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
stu.setId(rs.getInt("id"));
list.add(stu);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(conn, st, rs);
}
return null;
}
}
测试类:test.java
import java.util.List;
import org.junit.Test;
import dao.IStudentDao;
import .dao.impl.StudentDaoImpl;
importdomain.Student;
public class StudentDaoTest {
@Test
public void save() {
//创建一个学生
Student stu = new Student();
stu.setName("李白2");
stu.setAge(21);
//把学生保存到数据库当中
IStudentDao dao = new StudentDaoImpl();
dao.save(stu);
}
@Test
public void delete() {
IStudentDao dao = new StudentDaoImpl();
dao.delete(4);
}
@Test
public void update() {
IStudentDao dao = new StudentDaoImpl();
//创建一个学生
Student stu = new Student();
stu.setName("鲁班7");
stu.setAge(7);
dao.update(2, stu);
}
@Test
public void get(){
IStudentDao dao = new StudentDaoImpl();
Student stu = dao.get(2);
System.out.println(stu);
}
@Test
public void getAll(){
IStudentDao dao = new StudentDaoImpl();
List<Student> allStu = dao.getAll();
System.out.println(allStu);
}
}
事务及批处理:
假设有表account,zs要给ls转账
手动在第3步之前添加异常:int x = 1/0;发现zs账户减少,而ls账户没有增加。
处理事务过程
关闭自动提交conn.setAutoCommit(false);
没有问题时,提交事务conn.commit();
出现异常时,进行回滚操作conn.rollback(),回滚之后,事务结束。释放资源。
只有增、删、改才需要事务,查询不需要事务
什么是批处理
一次性执行多条Sql语句,允许多条语句一次性提交给数据库批量处理
批处理方法:addBatch(String),添加需要批处理的sql语句
executeBatch(),执批处理
mysql默认情况下是不支持批处理的
从5.1.13开始,添加了一个rewriteBatchedStatement参数
在配置文件中进行修改:
public static void main(String[] args) throws Exception {
Connection conn = JdbcUtil.getConn();
String sql = "insert into student (name,age) values (?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
long begin = System.currentTimeMillis();
for( int i = 0; i < 1000; i++) {
ps.setString(1, "zs");
ps.setInt(2, 10);
//添加到批处理
ps.addBatch();
}
//执行批处理
ps.executeBatch();
//清除缓存
ps.clearBatch();
//清除参数
ps.clearParameters();
long end = System.currentTimeMillis();
long time = end - begin;
System.out.println(time);
JdbcUtil.close(conn, ps, null);
}
网友评论