DAO设计模式,学习笔记

理解分层

前台:显示层和控制层

后台业务层:业务层和数据层,int ,double等业务层用基本类型,数据层用包装类

项目的核心是后台业务层,什么是业务层,什么是数据层?

业务层是整个程序提供的功能,而一个业务层的操作要想完成需要多个数据层的操作,数据层完成的只是一个个原子性的数据库操作,而我们在实际开发中, 每一个操作的业务往往需要牵扯到多个原子性的操作,也就是说所有的原子性的操作业务最终在业务层只能完成,如果业务非常复杂,往往需要一个总业务层,而后牵扯到若干个子业务层,每个子业务层再去操作数据层

by-pxc.png

数据层:又被称为数据访问层 (Data Access Object)DAO,是专门进行数据库的原子性操作,也就是在数据层中最需要控制的PreparedStatement接口的使用。

业务层:又被称为业务中心,业务对象(Business Object,BO),或者叫服务层(Service),核心的操作是调用DAO层的操作以完成整体项目的业务设计

DAO案例

任务:使用emp表(empno,ename,job,hiredate,sal,comm)实现以下操作功能

  • 【业务层】实现雇员的添加,但是要保证被添加的雇员编号不重复;
    |-[数据层]判断要增加的雇员编号是否存在

|-[数据层]如果雇员编号不存在则进行数据的保存操作

  • 【业务层】实现雇员的修改操作
    |-[数据层]执行数据修改操作

  • 【业务层】实现多个雇员的数据删除操作
    |-[数据层]执行多个雇员的数据删除操作

  • 【业务层】可以根据雇员编号找到一个雇员的信息
    |-[数据层]根据雇员编号查询指定的雇员数据

  • 【业务层】查询所有雇员的信息
    |-[数据层]查询全部的雇员数据

  • 【业务层】实现数据的分页显示(模糊查询)同时又可以返回所有的雇员信息
    |-[数据层]雇员数据的分页查询
    |-[数据层]使用COUNT()函数,统计所有雇员的数量

结论:用户所有的需求都是业务层,开发人员必须要根据业务层进行数据层的数据

项目准备

为了方便项目的管理所有的包的父包设置为com.pxc,子包要根据不同模块划分.定义数据库的连接类(DatabaseConnection)专门用于数据可以的连接操作,保存在bdc包中
<pre>package com.pxc.dbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
*用于数据库的连接和关闭操作,在实例化此类的时候就意味着数据库的开发
*所以在此类的构造方法中就要进行数据库驱动加载和数据库的连接取得
*@author PXC
*
*/
public class DatabaseConnection {
private static final String DBDRIVER="com.mysql.jdbc.Driver";
private static final String DBURL="jdbc:mysql://localhost:3306/mybatis";
private static final String USER="root";
private static final String PWD="935377012";
private Connection conn=null;
/**
* 在构造方法里为conn实例化
*/
public DatabaseConnection(){
try {
Class.forName(DBDRIVER);
try {
this.conn=DriverManager.getConnection(DBURL,USER,PWD);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void close(){
if(this.conn!=null){
try {
this.conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public Connection getConnection(){
return conn;
}
}</pre>

开发Value Object

不同层次之间必然要进行数据的传递,但是既然要操作的是指定的数据表,所以数据的结构要与表的结构一一对应,那么自然就想到是简单java类(po,to,pojo,vo)

简单java类有如下的要求

  1. 考虑到以后有可能出现的分布式应用问题,所以简单java类必须要实现java.io.Serializable接口;

  2. 简单java类的名称必须与表名称保持一致。表名称如果是这种stydent_info类名称为StudentInfo

3.类中的字段必须使用private封装,封装好的属性必须提供get和set方法

  1. 类中的属性不允许使用基本数据类型,都必须使用基本数据类型的包装类。原因是基本数据类型的默认值是0,而包装类的默认数据类型是null

  2. 类中必须保留无参构造方法

将所有的简单java类保存在vo包中

开发数据层操作标准

<pre>
package com.pxc.dao;
import java.security.PublicKey;
import java.util.List;
import java.util.Set;
import com.pxc.vo.Emp;
/***

  • 定义emp表的数据层的操作标准
  • @author PXC

/
public interface IEmpDAO {
/
**
* 实现数据的增加操作
* @param emp
* @return 数据保存成功返回true
* @throws Exception sql执行异常
/
public boolean doCreate(Emp emp)throws Exception;//简化开发,严格的话一定要挨个抛
/
**
* 实现数据的修改操作,本次修改是根据id进行全部字段的修改
* @param emp 包含了压迫修改的信息,一定要提供id
* @return 修改成功返回true
* @throws Exception sql执行异常
/
public boolean doUpdate(Emp emp)throws Exception;
/
*
* 执行数据的批量数据的操作,所有要删除的数据以Set集合形式保存
* @param ids 包含了所有要删除的数据ID,不包含重复内容
* @return 删除成功返回true(删除的数据个数和要删除的数据个数相同)
* @throws Exception
/
public boolean doRemoveBatch(Set ids) throws Exception;
/
**
* 根据编号查询指定的雇员信息
* @param id 要查询的雇员编号
* @return 如果雇员信息存在,则将数据以pojo返回,如果不存在则返回null
* @throws Exception
/
public Emp findById(Integer id)throws Exception;
/
*
* 查询指定表的全部记录,并且以集合的形式返回
* @return 如果表中有数据,则所有的数据都会被封装为pojo对象而后利用List集合返回,
* 如果没有数据则集合的长度为0,不是返回null
* @throws Exception SQL执行异常
/
public List findAll() throws Exception;
/
**
* 分页进行数据的模糊查询,查询的结果以集合的形式返回
* @param currentPage 当前所在的页
* @param lineSize 每页显示的行数
* @param column 要进行模糊查询的数据列
* @param keyWord 模糊查询的关键字
* @return 如果表中有数据,则所有的数据都会被封装为pojo对象而后利用List集合返回,
* 如果没有数据则集合的长度为0,不是返回null
* @throws Exception SQL执行异常
/
public List findAllSplit(Integer currentPage,Integer lineSize,String column,String keyWord)throws Exception;
/
**
* 进行模糊查询数据量的统计
* @param column 要进行模糊查询的数据列
* @param keyWord 模糊查询的关键字
* @return 返回表中的数据量,没有数据返回0
* @throws Exception SQL执行异常
*/
public Integer getAllCount(String column, String keyWord)throws Exception;
}
</pre>

数据层的实现类

数据层要被业务层调用,数据层要进行数据库的操作,由于在开发中一个业务层操作需要执行多个数据层的操作,所以数据库的打开和关闭操作应该由业务层操作。

所有的数据层数显类要保存在dao.impl子包下

范例:EmpDAOImpl子类
<pre>
package com.pxc.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.pxc.dao.IEmpDAO;
import com.pxc.vo.Emp;
public class EmpDAOImpl implements IEmpDAO {
private Connection conn;//需要利用connection对象
private PreparedStatement pstmt;
/**
* 如果要使用数据层进行原子性功能的操作实现,必须提供Connection接口对象
* 另外业务层要调用数据层,所以数据库的打开和关闭交给业务层处理
* @param conn 数据库的连接对象
*/
public EmpDAOImpl(Connection conn){
this.conn=conn;
}
@Override
public boolean doCreate(Emp emp) throws Exception {
String sql="insert into emp(empno,ename,job,hiredate,sal,comn) values(?,?,?,?,?,?)";
this.pstmt=this.conn.prepareStatement(sql);
this.pstmt.setInt(1, emp.getEmpno());
this.pstmt.setString(2, emp.getEname());
this.pstmt.setString(3, emp.getJob());
this.pstmt.setDate(4, new java.sql.Date(emp.getHiredate().getTime()));
this.pstmt.setDouble(5, emp.getSal());
this.pstmt.setDouble(6, emp.getComm());
return this.pstmt.executeUpdate()>0;
}
@Override
public boolean doUpdate(Emp emp) throws Exception {
String sql="update emp set ename=?,job=?,hiredate=?,sal=?,comn=? where empno=?";
this.pstmt=this.conn.prepareStatement(sql);
this.pstmt.setString(1, emp.getEname());
this.pstmt.setString(2, emp.getJob());
this.pstmt.setDate(3, new java.sql.Date(emp.getHiredate().getTime()));
this.pstmt.setDouble(4, emp.getSal());
this.pstmt.setDouble(5, emp.getComm());
this.pstmt.setInt(6, emp.getEmpno());
return this.pstmt.executeUpdate()>0;
}
@Override
public boolean doRemoveBatch(Set ids) throws Exception {
if(ids==null||ids.size()==0){//没有要删除的数据
return false;
}
StringBuffer sql=new StringBuffer();
sql.append("delete from emp where empno in(");
Iterator iter=ids.iterator();
while(iter.hasNext()){
sql.append(iter.next()+",");
}
sql.delete(sql.length()-1, sql.length()).append(")");
this.pstmt=this.conn.prepareStatement(sql.toString());
return this.pstmt.executeUpdate()==ids.size();

}
@Override
public Emp findById(Integer id) throws Exception {
    Emp emp=null;
    String sql="select * from emp where empno=?";
    this.pstmt=this.conn.prepareStatement(sql);
    pstmt.setInt(1,id);
    ResultSet rs=pstmt.executeQuery();
    if(rs.next()){
        emp.setEmpno(rs.getInt(1));
        emp.setEname(rs.getString(2));
        emp.setJob(rs.getString(3));
        emp.setHiredate(rs.getDate(4));
        emp.setSal(rs.getDouble(5));
        emp.setComm(rs.getDouble(6));
    }
    return emp;
}
@Override
public List findAll() throws Exception {
    List all =new ArrayList();
    String sql="select * from emp";
    this.pstmt=this.conn.prepareStatement(sql);
    ResultSet rs=pstmt.executeQuery();
    while(rs.next()){
        Emp emp=new Emp();
        emp.setEmpno(rs.getInt(1));
        emp.setEname(rs.getString(2));
        emp.setJob(rs.getString(3));
        emp.setHiredate(rs.getDate(4));
        emp.setSal(rs.getDouble(5));
        emp.setComm(rs.getDouble(6));
        all.add(emp);
    }
    return all;
}
@Override
public List findAllSplit(Integer currentPage, Integer lineSize, String column, String keyWord)
        throws Exception {
    // TODO Auto-generated method stub
    return null;
}
@Override
public Integer getAllCount(String column, String keyWord) throws Exception {
    String sql="select count(*) from emp where "+column+"like ?";
    this.pstmt=this.conn.prepareStatement(sql);
    this.pstmt.setString(1,"%"+keyWord+"%");
    ResultSet rs=pstmt.executeQuery();
    if(rs.next()){
        return rs.getInt(1);
    }
    return 0;
}

}</pre>

定义数据层工厂类

<pre>package com.pxc.factory;
import java.sql.Connection;
import com.pxc.dao.IDeptDAO;
import com.pxc.dao.IEmpDAO;
import com.pxc.dao.impl.DeptDAOImpl;
import com.pxc.dao.impl.EmpDAOImpl;
public class DAOFactory {
public static IEmpDAO getIEmpDAOInstance(Connection conn){
return new EmpDAOImpl(conn);
}

}</pre>

定义业务层执行标准

<pre>package com.pxc.service;
import java.util.Set;
import java.util.List;
import java.util.Map;
import com.pxc.vo.Emp;
/***
* 定义emp表的业务层的执行标准,此类一定要负责数据库的打开和关闭操作
*此类可以通过DAOFactory类取得IEmpDAO的接口对象
* @author PXC
*
*/
public interface IEmpService {
/***
* 实现雇员数据的增加操作,本次操作要调用IEmpDAO接口的如下方法

* 需要调用IEmpDAO.findById()方法,判断是否已经存在
* 如果现在要增加的数据编号不存在则调用IEmpDAO.doCreate()方法,返回操作的结果
* @param emp 包含了要增加数据的pojo对象
* @return 如果增加数据的ID重复或者保存失败返回false,否则返回true
* @throws Exception SQL、执行异常
*/
public boolean insert(Emp emp)throws Exception;
/***
* 实现雇员的修改操作,本次调用的是IEmpDAO.doupdate()方法,本次修改属于全部内容修改
* @param emp 包含了要增加数据的pojo对象
* @return 修改成功返回true否则赶回false
* @throws Exception SQL执行异常
*/
public boolean update(Emp emp) throws Exception;
/**
* 执行雇员数据的删除,删除多个雇员信息,调用IEmpDAo.doRemoveBatch()方法
* @param ids 包含了要删除数据的集合,没有重复数据
* @return 删除成功返回true否则赶回false
* @throws Exception SQL执行异常
*/
public boolean delete(Set<Integer> ids) throws Exception;
/
**
* 根据雇员编号查找雇员完整信息,调用IEmpDAO.findById()方法
* @param ids 要查找的雇员编号
* @return 如果找到雇员信息则以pojo返回,否则返回null
* @throws Exception SQL执行异常
*/
public Emp get(Integer ids)throws Exception;
/**
* 查询全部雇员信息,调用的是IEmpDAO中的findAll()方法
* @return 查询结果以List集合形式返回。如果没有结果则返回0。
* @throws Exception SQL执行异常
*/
public List<Emp> list()throws Exception;
/
**
* 实现数据的模糊查询和数据的统计,调用

* IEmpDAO.findAllSplit()方法,返回List集合数据
* IEmpDAO.getAllCount()方法,返回的是integer类型
* @param currentPage 当前所在页
* @param lineSize 每页显示的记录数
* @param column 模糊查询的数据列
* @param keyWord 模糊查询的关键字
* @return 本方法要返回多种数据类型,所以使用Map结婚,由于类型不统一,所有value的类型设置为Object,返回内容如下

* key=allEmps,value=IEmpDAO.findAllSplit()返回结果,LIst集合
* key=empCOunt,value=IEmpDAO.getAllCount()返回结果,Integer
* @throws Exception
*/
public Map<String,Object> List(int currentPage,int lineSize,String column,String keyWord) throws Exception;
}</pre>

业务层的实现类

业务层实现类的核心功能

  • 负责控制数据库的打开和关闭。业务层对象实例化之后必须准备好数据库的连接

  • 根据DAOFactory调用getIEmpDAO Instance()方法而后取得IEmpDAO接口对象,业务层的实现类保存在dao.impl子包中
    <pre>
    package com.pxc.service.impl;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import com.pxc.dbc.DatabaseConnection;
    import com.pxc.factory.DAOFactory;
    import com.pxc.service.IEmpService;
    import com.pxc.vo.Emp;
    public class EmpServiceImpl implements IEmpService {
    // 在这个类的内部就提供一个数据库实例化对象
    private DatabaseConnection dbc = new DatabaseConnection();
    @Override
    public boolean insert(Emp emp) throws Exception {
    // TODO Auto-generated method stub
    try {
    //要增加的雇员编号不存在,findById()返回的结果接受null,null表示可以进行新雇员信息的保存
    if(DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findById(emp.getEmpno())==null){
    return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doCreate(emp);
    }
    return false;
    } catch (Exception e) {
    throw e;
    } finally {
    this.dbc.close();
    }

    }
    @Override
    public boolean update(Emp emp) throws Exception {
    // TODO Auto-generated method stub
    try {
    return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doUpdate(emp);
    } catch (Exception e) {
    throw e;
    } finally {
    this.dbc.close();
    }
    }

    @Override
    public boolean delete(Set ids) throws Exception {
    try {
    return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doRemoveBatch(ids);
    } catch (Exception e) {
    throw e;
    } finally {
    this.dbc.close();
    }
    }
    @Override
    public Emp get(Integer id) throws Exception {

try {
return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findById(id);
} catch (Exception e) {
throw e;
} finally {
this.dbc.close();
}
}

@Override
public java.util.List list() throws Exception {
try {
return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findAll();
} catch (Exception e) {
throw e;
} finally {
this.dbc.close();
}
}

@Override
public Map<String, Object> List(int currentPage, int lineSize, String column, String keyWord) throws Exception {
try {
Map<String, Object> map=new HashMap<String, Object>();
map.put("allEmps", DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findAllSplit(currentPage, lineSize, column, keyWord));
map.put("empCount", DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).getAllCount(column, keyWord));
return map;
} catch (Exception e) {
throw e;

} finally {
this.dbc.close();
}
}

}</pre>

不同层的访问就是依靠的工厂类和接口进行操作,写了接口,取得对象就用工厂类

定义业务层的工厂类

业务层要被控制层调用,所以要为业务层定义工厂类,该类也保存在factory子包下,业务层应该分为两种

  • 前台业务逻辑:可以将其保存在service.front包中,工厂类:serviceFrontFactory
  • 后台业务逻辑:可以将其保存在service.back包中,工厂类:serviceBackFactory
    范例定义serviceFactory(本次不区分前后台)
    <pre>package com.pxc.factory;
    import com.pxc.service.IEmpService;
    import com.pxc.service.impl.EmpServiceImpl;
    public class ServiceFactory {
    public static IEmpService getIeEmpServiceInstance(){
    return new EmpServiceImpl();
    }
    }</pre>

在实际编写中,子类永远是不可见的,控制层完全看不见数据库的任何操作。

代码测试

最终的业务层是需要用户去调用的,所以测试分为两种。

  • 调用测试
    按照传统方式产生对象,而后调用里面的方式操作,保存在test子包类
    测试案例:
    <pre>package com.pxc.test;
    import java.util.Date;
    import com.pxc.factory.ServiceFactory;
    import com.pxc.vo.Emp;
    public class TestEmpInsert {
    public static void main(String[] args) {
    Emp emp=new Emp();
    emp.setEmpno(456);
    emp.setEname("pxc");
    emp.setJob("IT");
    emp.setHiredate(new Date());
    emp.setSal(0.5);
    emp.setComm(10.0);
    try {
    System.out.println(ServiceFactory.getIeEmpServiceInstance().insert(emp));
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    };
    }
    }</pre>

  • 利用junit进行测试
    对于这种业务的测试使用junit是最好的选择,首先要选择类或者接口进行测试,本次使用IEmpService
    <pre>package com.pxc.test.junit;
    import static org.junit.Assert.*;
    import java.util.Date;
    import java.util.Random;
    import org.junit.Test;
    import com.pxc.factory.ServiceFactory;
    import com.pxc.vo.Emp;
    import junit.framework.TestCase;
    public class IEmpServiceTest {
    private static int empno ;
    static{
    empno=new Random().nextInt(10000);//动态生成empno 的数据
    }
    @Test
    public void testInsert() {
    Emp emp = new Emp();
    emp.setEmpno(empno);
    emp.setEname("pxc2"+empno);
    emp.setJob("IT"+empno);
    emp.setHiredate(new Date());
    emp.setSal(0.5);
    emp.setComm(10.0);
    try {
    TestCase.assertTrue(ServiceFactory.getIeEmpServiceInstance().insert(emp));
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    };
    }
    @Test
    public void testUpdate() {
    Emp emp=new Emp();
    emp.setEmpno(2);
    emp.setEname("pxc5");
    emp.setJob("IT");
    emp.setHiredate(new Date());
    emp.setSal(0.5);
    emp.setComm(10.0);
    try {
    TestCase.assertTrue(ServiceFactory.getIeEmpServiceInstance().update(emp));
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    };
    }
    @Test
    public void testList() {
    try {
    TestCase.assertTrue(ServiceFactory.getIeEmpServiceInstance().list().size()>0);
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    }
    }
    </pre>


以上就是我在学习DAO时做的笔记,本次只涉及到单表查询,等熟练运用单表查询后,再去考虑多表查询。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,103评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,296评论 18 399
  • JAVA面试题 1、作用域public,private,protected,以及不写时的区别答:区别如下:作用域 ...
    JA尐白阅读 1,124评论 1 0
  • SQL ==SQLPLUS== DML(Data Manipulation Language,数据操作语言)---...
    蝌蚪1573阅读 552评论 0 4
  • 这个周三要出差,从周末开始,我就已经做好了各种放假的准备。 但事实并非如此。周一上午开发票、买...
    云中看花阅读 91评论 0 0