1.Database Access Object:数据库访问(存取)对象,专门用于业务逻辑层与持久化数据之间,实现持久化数据的访问。专门与数据库打交道的层。 所谓DAO层是从系统分层结构出发,把数据存取操作集中到DAO层,以便于维护和逻辑清晰。
所以设计了DAO之后我们不需要在主函数中去调用数据库操作,而是在Service层进行数据库操作,我们只需要调用Service层的方法就好了。
2.ORM(对象关系映射):使用反射机制实现的使数据库中读出的记录能与实体类对象进行映射的操作;
3.DAO设计时的顺序:
(1)先设定一个统一DAO的接口用来限制功能与降低耦合性;
(2)再编写一个BaseDAO作为抽象基类,实现接口的方法,使用泛型完成一些重复度比较高的操作,并留出一些个性化的方法留给子类来实现;
(3)编写子类,使其继承父类的方法,并可根据泛型指定父类没有指定的类型;
4.这里是我自己编写的DAO模式:
java
public interface EmpDAO {
public Emp selectById(Object id);
public List<Emp> selectList();
}
java
public class BaseDAO<T> {
private Class<T> persistentClass;
public BaseDAO() {
Type genType = this.getClass().getGenericSuperclass();
if (genType instanceof ParameterizedType) {
persistentClass = (Class<T>) ((ParameterizedType) genType).getActualTypeArguments()[0];
}
}
public int save(T entity) {
Class<?> clazz = entity.getClass();
Field[] fields = clazz.getDeclaredFields();
Object[] values = new Object[fields.length];
idType idType = null;
for(Field field : fields){
TableId annotation = field.getAnnotation(TableId.class);
if(annotation != null){
idType = annotation.value();
break;
}
}
StringBuilder stringBuilder = new StringBuilder();
//insert into 表名(字段1,字段2,字段3...)values()
stringBuilder.append("insert into ");
stringBuilder.append(persistentClass.getSimpleName());
stringBuilder.append("(");
int index =0;
for(Field field : fields){
field.setAccessible(true);
stringBuilder.append(field.getName()).append(",");
try {
values[index++] = field.get(entity);
}catch (IllegalAccessException e){
e.printStackTrace();
}
}
stringBuilder.setCharAt(stringBuilder.length()-1,')');
stringBuilder.append("values(");
for(Field field : fields){
stringBuilder.append("?").append(",");
}
stringBuilder.setCharAt(stringBuilder.length()-1,')');
int index1 = stringBuilder.indexOf("?");
if(idType == demo.idType.UUID){
values[0] = UUID.randomUUID().toString().replace("-","");
}else if(idType ==demo.idType.AUTO_INCREMENT ){
stringBuilder.replace(index1,index1+1,"default");
values = Arrays.copyOfRange(values,1,values.length);
}
stringBuilder.setCharAt(stringBuilder.length()-1,')');
DBUtil.executeUpdatePrepared(stringBuilder.toString(),values);
return DBUtil.executeUpdatePrepared(stringBuilder.toString(),values);
}
public int delete(Object id) {
StringBuilder stringBuilder = new StringBuilder();
String simpleName = persistentClass.getSimpleName();
stringBuilder.append("delete from ");
stringBuilder.append(simpleName);
stringBuilder.append(" where id=?");
return DBUtil.executeUpdatePrepared(stringBuilder.toString(),id);
}
public int update(T entity) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("update ");
stringBuilder.append(persistentClass.getSimpleName().toLowerCase());
stringBuilder.append(" set ");
Field[] fields = persistentClass.getDeclaredFields();
Object[] values = new Object[fields.length];
try {
for(int i = 1; i < fields.length; i++){
fields[i].setAccessible(true);
stringBuilder.append(fields[i].getName()).append("=?,");
values[i-1] = fields[i].get(entity);
}
fields[0].setAccessible(true);
values[values.length-1]=fields[0].get(entity);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
stringBuilder.deleteCharAt(stringBuilder.length()-1);
stringBuilder.append(" where ");
stringBuilder.append(fields[0].getName()).append("=?");
return DBUtil.executeUpdatePrepared(stringBuilder.toString(),values);
}
}
java
public class Emp {
@TableId(idType.AUTO_INCREMENT)
private Integer id;
private String name;
private String gender;
private Boolean depart;
private Float sal;
private Date hiredate;
public Emp() {}
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Boolean isDepart() {
return depart;
}
public void setDepart(Boolean depart) {
this.depart = depart;
}
public Float getSal() {
return sal;
}
public void setSal(Float sal) {
this.sal = sal;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
@Override
public String toString() {
return "emp{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", depart=" + depart +
", sal=" + sal +
", hiredate=" + hiredate +
'}';
}
}
java
public class DBUtil {
private static String URL;
private static String USERNAME;
private static String PASSWORD;
private static String DRIVER;
private static String CONNECTION_POOL_NAME;
static {
ResourceBundle rb = ResourceBundle.getBundle("info");
URL = rb.getString("jdbc.url");
USERNAME = rb.getString("jdbc.username");
PASSWORD = rb.getString("jdbc.password");
DRIVER = rb.getString("jdbc.driver");
CONNECTION_POOL_NAME = rb.getString("pool.class1");
}
public static Connection getConnection() {
if (CONNECTION_POOL_NAME.equals(DruidDataSource.class.getName())) {
/*DruidDataSource ds = new DruidDataSource();
ds.setUrl(URL);
ds.setUsername(USERNAME);
ds.setPassword(PASSWORD);
}*/
try {
Class<?> clazz = DruidDataSource.class;
Object o1 = clazz.getConstructor().newInstance();
Method setUrl = clazz.getMethod("setUrl", String.class);
setUrl.invoke(o1, URL);
Method setUsername = clazz.getMethod("setUsername", String.class);
setUsername.invoke(o1, USERNAME);
Method setPassword = clazz.getMethod("setPassword", String.class);
setPassword.invoke(o1, PASSWORD);
Method setDriver = clazz.getMethod("setDriverClassName", String.class);
setDriver.invoke(o1, DRIVER);
Method getConnection = clazz.getMethod("getConnection");
clazz.getMethod("setInitialSize", int.class).invoke(o1, 5);
clazz.getMethod("setMaxActive", int.class).invoke(o1, 20);
clazz.getMethod("setMinIdle", int.class).invoke(o1, 10);
return (Connection) getConnection.invoke(o1);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
try {
Class<?> clazz = HikariDataSource.class;
Object o2 = clazz.getConstructor().newInstance();
Method setUrl = clazz.getMethod("setJdbcUrl", String.class);
setUrl.invoke(o2, URL);
Method setUsername = clazz.getMethod("setUsername", String.class);
setUsername.invoke(o2, USERNAME);
Method setPassword = clazz.getMethod("setPassword", String.class);
setPassword.invoke(o2, PASSWORD);
Method setDriver = clazz.getMethod("setDriverClassName", String.class);
setDriver.invoke(o2, DRIVER);
Method getConnection = clazz.getMethod("getConnection");
return (Connection) getConnection.invoke(o2);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static int[] executeUpdateBatch(String sql,Object[] ... args) {
Connection conn = getConnection();
PreparedStatement ps = null;
try{
ps = conn.prepareStatement(sql);
conn.setAutoCommit(false);
for(Object[] arg : args) {
int j = 1;
for(Object o : arg) {
ps.setObject(j++, o);
}
ps.addBatch();
}
int[] re = ps.executeBatch();
conn.commit();
close(conn,ps);
return re;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void close(Connection conn, Statement ps) {
try {
conn.close();
ps.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static int executeUpdatePrepared(String sql,Object ... args){
Connection conn = getConnection();
PreparedStatement pstmt = null;
try{
pstmt = conn.prepareStatement(sql);
int i = 1;
for(Object arg : args){
pstmt.setObject(i++,arg);
}
int m = pstmt.executeUpdate();
return m;
}catch (SQLException e){
throw new RuntimeException(e);
}finally {
close(conn,pstmt);
}
}
public static DBObject executeQueryPrepared(String sql,Object ... args){
Connection conn = getConnection();
PreparedStatement pstmt = null;
DBObject obj = null;
try{
pstmt = conn.prepareStatement(sql);
int i = 1;
for(Object arg : args){
pstmt.setObject(i++,arg);
}
obj = new DBObject(conn,pstmt,pstmt.executeQuery());
}catch (SQLException e){
throw new RuntimeException(e);
}
return obj;
}
public static void close(DBObject obj){
close(obj.getConn(), obj.getStmt());
}
}
java
public class DBObject {
Connection conn;
Statement stmt;
ResultSet rs;
public DBObject() {}
public DBObject(Connection conn, Statement stmt, ResultSet rs) {
this.conn = conn;
this.stmt = stmt;
this.rs = rs;
}
public Connection getConn() {
return conn;
}
public void setConn(Connection conn) {
this.conn = conn;
}
public Statement getStmt() {
return stmt;
}
public void setStmt(Statement stmt) {
this.stmt = stmt;
}
public ResultSet getRs() {
return rs;
}
public void setRs(ResultSet rs) {
this.rs = rs;
}
}
这就是几个必要的DB工具类,实体类,实现了之后只需要调用BaseDAO和empDAO的方法就好了;
5.JDBC的事务处理:
操作流程:开启事务Connection.setAutoCommit(false);
提交事务Connection.commit;
回滚事务Connection.rollback();
6.保存点SavePoint
Connection.rollback(SavePoint);
7.Apache DbUti工具类的使用:
和我们自己编写的数据库工具类相似,可以使用线程池,也可以直连,可以执行dml,ddl,dql操作,如果是dql操作可以指定获取的结果的类型,比如说map、List这种集合类也是可以的;
API调用:
QueryRunner,主要的工具类,可以传入数据源,也可以不传入数据源;
RunnerSetHandler:类型转换接口,将结果集转换为对应数据类型;
BeanHandler:是ResultSetHandler的实现类,将结果封装为一个java对象中,传入Class类,以指定返回值的类型;
BeanListHandler:是ResultSetHandler的实现类,将结果转换为List,可以将多行的结果集存储在一个实体类List中;
MapHandler:将结果集中的第一行数据封装到一个Map中,Key是String类型,是数据库查询的列名,value是Object,数据库中对应值;
ScalarHandler:将第一行数据的指定列数据返回,可强转为泛型中的数据类型;
MapListHandler:将结果集中的每一行行数据封装为一个map加入到List中;