一:ORM(Object Relationship Mapping)
对象关系映射,一行数据与一个实体对象的对应。
I.将一行零散数据进行一次整理(一行数据--->一个实例)
II.表名 = 类名;字段名 = 属性名;
III.提供Getters and Setters、无参构造方法。
对于日期类型:Java中存在两种java.util.Date和java.sql.Date。
①.java.util.Date:
I.Java语言常规应用层的日期类型,支持直接获取当前系统时间、可通过自定义字符串进行创建。
II.无法直接插入数据库。
②.java.sql.Date:
I.数据库应用的日期类型,必须借助1970年起的毫秒值进行创建。
II.可以直接插入数据库。
③.java.text.SimpleDateFormat:
I.将字符串与java.util.Date相互转换。
II.SimpleDateFormat sdf = new SimpleDateFormat("格式化字符串");
III.sdf.parse(); //字符串转java.util.Date();
IV.sdf.format();//将日期格式化为字符串
④.注意:
java.util.Date:Fri Aug 08 11:59:59 CST 2008
java.sql.Date:yyyy-MM-dd(覆盖了父类提供的toString())
SimpleDateFormat sdf = new SimpleDateFormat(yyyy-MM-dd hh:mm:ss);
格式化的字符串 = sdf.format(utilDate);
对日期类型转换的封装public class DateConvertUtil {
private static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//将字符串转为java.util.Date 为了将字符串日期存入实体类中
public static java.util.Date toUtilDate(String date){
try {
return sdf.parse(date);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//将java.util.Date转为java.sql.Date 为了向数据库中存
public static java.sql.Date toSqlDate(java.util.Date date){
return new java.sql.Date(date.getTime());
}
//将java.util.Date转为String 为了view页面展示
public static String toString(java.util.Date date){
return sdf.format(date);
}
}
二:DAO(Data Access Object)数据访问层
将对一张表的操作(增删改查),封装在一个对象的多个方法中。
根据不同需求提供对应的方法(insert、update、delete、select、selectAll)。
三:Service(Biz/Business)业务逻辑层
代表面向用户的一个功能,可以由一次或多次的DAO调用组成。
I.数据操作的复用:DAO数据访问对象
II.业务功能的复用:Service业务逻辑对象
四:事务控制
1.事务的边界:业务方法的首行-->整个方法结束(全部视为原子操作,要成功、都成功;要失败、都失败。)
2.手动控制事务:
I.修改事务提交方案:conn.setAutoCommit(false);
II.conn.commit();
III.conn.rollback();
IV.try catch final:异常的向上报告,连接对象的释放。
ThreadLocal对象:
I. 线程工具类:可以在整个线程(单条执行路径)所持有的Map中,存储一个键(threadlocal)值(conn)。
II. 将参数对象(Connection conn)添加到当前线程中:
private static final ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); //工具类
III. 修改getConnection方法:
Connection conn = tl.get(); //获取线程中保存的Connection对象
if(conn == null){ //当线程中没有保存过Connection对象时
conn = DriverManager.getConnection(url, userName, password); //获取连接对象
tl.set(conn); //并保存至线程中
}
return conn;
IV. 在release中关闭conn时,同时tl.remove(); //移除线程中的连接对象,只有业务提交或回滚之后才关闭、移除连接。
get() |
|
void |
remove() |
void |
//加入ThreadLocal的JDBC封装
public class JDBCUtil {
private static final Properties pro=new Properties();
private static ThreadLocal<Connection> tl=new ThreadLocal<Connection>();
static{
try {
InputStream is=new FileInputStream("bin//jdbc.properties");
pro.load(is);
String classname=pro.getProperty("classname");
Class.forName(classname);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection conn=tl.get();
try{
if(conn==null){
String url=pro.getProperty("url");
String user=pro.getProperty("user");
String pwd=pro.getProperty("pwd");
conn=DriverManager.getConnection(url, user, pwd);
tl.set(conn);
}
}catch (Exception e){
e.printStackTrace();
}
return conn;
}
public static void relise(ResultSet rs,PreparedStatement prsm, Connection conn){
try{
if(rs!=null)
rs.close();
if(prsm!=null)
prsm.close();
if(conn!=null){
conn.close();
tl.remove();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
事务由service层开启,service层完成提交或回滚
public boolean addStudent(Student stu) {
boolean flag=false;
try{
TransactionManager.begin();//开启事务
int count= dao.insert(stu);
if(count>0)
flag=true;
TransactionManager.commit();//提交事务
}catch(Exception e){
TransactionManager.rollback();//回滚事务
throw new RuntimeException(e);
}
return flag;
}
五:事务的封装
public class TransactionManager {
//开启事务
public static void begin(){
Connection conn=JDBCUtil.getConnection();
try {
conn.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
//提交事务
public static void commit(){
Connection conn=JDBCUtil.getConnection();
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtil.relise(null, null, conn);
}
}
//回滚事务
public static void rollback(){
Connection conn=JDBCUtil.getConnection();
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtil.relise(null, null, conn);
}
}
}
六:DAO层的再封装
①:对于增删改操作,除了SQL语句不同,绑定的参数不确定,返回值以及其它代码完全一致。
prsm.setObject(1, “id”);
因此,我们可以动态传入sql语句, 对需要绑定参数用可变长参数 包装成Object 进行统一封装。
②:对查询操作
为了使工具具有通用性,我们利用泛型+接口回调的方式,让实体类自己实现对应对象封装的方法。
接口:
public interface Encaplation<T> {
public T encap(ResultSet rs);
}
实体实现接口的封装方法:
public class EncaplationStudent implements Encaplation<Student>{
@Override
public Student encap(ResultSet rs) {
try{
return new Student(rs.getString(1),rs.getString(2),rs.getString(3),rs.getString(4),rs.getDate(5),rs.getString(6));
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
对增删改查操作的再封装:
public class JDBCTemplate<T> {
public int commontUpadte(String sql,Object... parm){
Connection conn=JDBCUtil.getConnection();
PreparedStatement prsm=null;
try{
prsm=conn.prepareStatement(sql);
for(int i=0;i<parm.length;i++){
prsm.setObject(i+1, parm[i]);
}
return prsm.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtil.relise(null, prsm, null);
}
return 0;
}
public List<T> commontQuery(String sql , Encaplation<T> en, Object... params){
List<T> list = new ArrayList<T>();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
ps = conn.prepareStatement(sql);
// 绑定参数
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
rs = ps.executeQuery();
while(rs.next()){
//ORM(一行数据对应一个实体的封装)
T t = en.encap(rs);
list.add(t);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.relise(rs, ps, null);
}
return list;
}
}