做好了基本的准备工作,我们先从最简单的包开始下手,这个比较简单,我就直接上代码了,大家可以根据自己的需求自行添加字段到数据库,然后完善我们的JavaBean
User
@Table(value="u_user")
public class User {
@Column(value="id")
private int id;
@Column(value="user_name")
private String userName;
@Column(value="password")
private String password;
@Column(value="real_name")
private String realName;
public User() {
}
public User(int id, String userName, String password, String realName) {
super();
this.id = id;
this.userName = userName;
this.password = password;
this.realName = realName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", password=" + password + ", realName=" + realName + "]";
}
}
Customer
@Table(value="c_customer")
public class Customer {
@Column(value="id")
private int id;
@Column(value="cust_name")
private String custName;
@Column(value="cust_comp")
private String custComp;
public Customer() {
super();
}
public Customer(int id, String custName, String custComp) {
super();
this.id = id;
this.custName = custName;
this.custComp = custComp;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustComp() {
return custComp;
}
public void setCustComp(String custComp) {
this.custComp = custComp;
}
@Override
public String toString() {
return "Customer [id=" + id + ", custName=" + custName + ", custComp=" + custComp + "]";
}
}
Constract
@Table(value="c_contract")
public class Contract {
@Column(value="id")
private int id;
@Column(value="sale_id")
private int saleId;
@Column(value="cust_id")
private int custId;
@Column(value="content")
private String content;
@Column(value="create_time")
private String createTime;
public Contract() {
super();
}
public Contract(int id, int saleId, int custId, String content, String createTime) {
super();
this.id = id;
this.saleId = saleId;
this.custId = custId;
this.content = content;
this.createTime = createTime;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getSaleId() {
return saleId;
}
public void setSaleId(int saleId) {
this.saleId = saleId;
}
public int getCustId() {
return custId;
}
public void setCustId(int custId) {
this.custId = custId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Contract [id=" + id + ", saleId=" + saleId + ", custId=" + custId + ", content=" + content
+ ", createTime=" + createTime + "]";
}
}
另外我们还需要建一个com.marco.crs.vo包中新建一个ContractVO里面多添加两条字段
String saleName和String custName,这个主要是为了后期在我们页面上显示使用到的一个特殊类
vo包也就是value object,因为我们存入的对象可能跟后期展示出来的并不一定是同一个,vo中类的属性一般比bean中的更多,换句话来说vo中类查出来的信息就是多表联合查询出来的信息整理出来的新对象。
接下来就是我们的Dao层,这一层主要和数据库打交道,并且只用完成获取数据的操作
Dao接口
定义接口的目的是为了约定某种规范,然后由实现类具体的去实现它的方法,说白了,接口就好比XXX公司老板,它大致规划了公司的章程或者公司的发展规划,那么他底下的员工们就应当严格遵守他的规章制度,不同的部门可以完善他指定的规则,可能每个部门的规则不会完全一样,但是基本的骨架是一样的,这样的话就可以达成某种一致性,而且也便于管理。
public interface UserDao {
/*分页查询*/
PageQueryInfo listUsers(Map<String, Object> map);
/*添加用户*/
boolean addUser(User user) throws SQLException;
/*删除用户*/
boolean delUser(List<Integer> ids);
/*修改用户*/
boolean editUser(User user) throws SQLException;
/*用id查询用户*/
User queryById(int id);
}
public interface CustomerDao {
/*分页查询*/
PageQueryInfo listCustomers(Map<String, Object> map);
/*添加客户*/
boolean addCustomer(Customer customer) throws SQLException;
/*删除客户*/
boolean delCustomer(List<Integer> ids);
/*编辑客户*/
boolean editCustomer(Customer customer) throws SQLException;
/*根据客户id查询客户*/
Customer queryById(int id);
}
public interface ContractDao {
/*分页查询*/
PageQueryInfo listContracts(Map<String, Object> map);
/*添加合同*/
boolean addContract(Contract contract) throws SQLException;
/*删除合同*/
boolean delContract(List<Integer> ids) throws SQLException;
}
为了使JDBC的操作能够统一,我将此前封装的JDBC通用操作全部封装到BaseDao中,便于DaoImpl实现类能直接调用
public abstract class BaseDao {
public <T> List<T> queryData(Connection conn,Class<T> clz, String sql, Object...param) {
//创建连接对象
try {
PreparedStatement ps = conn.prepareStatement(sql);//创建操作数据库对象
//设置条件判断中的值
for(int i = 0; i < param.length; i++) {
ps.setObject(i+1, param[i]);
}
ResultSet rs = ps.executeQuery();//获取结果集对象
ResultSetMetaData meta = rs.getMetaData();//获取数据集元信息
int column = meta.getColumnCount();//获取所搜寻的字段个数或者列数
List<T> list = new ArrayList<>();//创建用于储存构建出来的对象的容器
while(rs.next()) {
Map<String,Object> map = new HashMap<>();//创建用于储存保存类的属性的map集合
for(int i = 0; i < column; i++) {
String columnName = meta.getColumnLabel(i+1);//得到每一列的或者每一个字段的名称
Object obj = rs.getObject(columnName);//根据字段名称获取每一行对应的字段值
map.put(columnName, obj);
}
if(!map.isEmpty()) {
T obj = clz.newInstance();//通过传入的类的Class对象创建这个类的对象
Set <Entry <String,Object>> entryset = map.entrySet();
for (Entry<String, Object> entry : entryset) {
String atribute = entry.getKey();//提取这个类中的属性名称
Object value = entry.getValue();//提取这个类中属性的值
Field attribute = clz.getDeclaredField(atribute);
attribute.setAccessible(true);//注意要设置权限为开放
attribute.set(obj, value);//通过反射给对象赋值
}
list.add(obj);//将赋值完成的对象放入ArrayList容器中
}
}
ConnPool.realse(rs, ps);
return list;
} catch (SQLException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return null;
}
private Map<String,Object> getAnnotations(Object obj) {
Map<String,Object> map = new HashMap<>();
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field field : declaredFields) {
Column anno = field.getAnnotation(Column.class);
if(anno!=null){
String attribute = anno.value();
try {
field.setAccessible(true);
Object value = field.get(obj);
map.put(attribute, value);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return map;
}
public <T> Boolean addData(Connection conn,T obj) throws SQLException {
Map<String, Object> map = getAnnotations(obj);
StringBuffer sql = new StringBuffer("insert into ");
int size = 0;//需要查询的字段的总长度
int index = 1;
Class<? extends Object> clz = obj.getClass();
sql.append(clz.getAnnotation(Table.class).value());
sql.append("(");
Set<Entry<String, Object>> entryset = map.entrySet();
Iterator<Entry<String,Object>> it = entryset.iterator();
while(it.hasNext()) {
Entry<String,Object> entry = it.next();
String attribute = entry.getKey();
sql.append(attribute);
sql.append(",");
size++;
}
sql.setCharAt(sql.lastIndexOf(","), ')');
sql.append("values(");
for (int i = 0; i < size; i++) {
sql.append("?");
sql.append(",");
}
sql.setCharAt(sql.lastIndexOf(","), ')');
PreparedStatement ps = conn.prepareStatement(sql.toString());
System.out.println(sql.toString());
Set<Entry<String, Object>> entryset2 = map.entrySet();
Iterator<Entry<String,Object>> it2 = entryset2.iterator();
while(it2.hasNext()) {
Entry<String,Object> entry = it2.next();
ps.setObject(index++, entry.getValue());
}
if(ps.executeUpdate()!=-1) {
ConnPool.realse(ps);
return true;
} else {
return false;
}
}
public <T> Boolean deleteData(Connection conn,String tableName,String keyword, List<Integer> list) {
PreparedStatement ps = null;
String sql = "delete from "+ tableName + " where " + keyword + " = ?";
try {
conn.setAutoCommit(false);
ps = conn.prepareStatement(sql);
for (Integer id : list) {
ps.setObject(1, id);
ps.addBatch();
}
ps.executeBatch();
conn.commit();
return true;
} catch (SQLException e) {
e.printStackTrace();
return false;
} finally {
ConnPool.realse(ps);
}
}
protected <T> PageQueryInfo queryPage(int currentPage, int limit, String sql, Class<T> clz, Connection conn) throws SQLException {
//每一页从哪一条开始
int count = this.countPage(sql, conn);
//当前页的第一行是在总行数的第几行
int startPage = (currentPage - 1)*limit;
sql += " limit " + startPage + "," + limit;
System.out.println(sql);
List<T> data = this.queryData(conn, clz, sql);
PageQueryInfo info = new PageQueryInfo();
//总页数
int totalPage = count%limit == 0?count/limit:(count/limit + 1);
info.setData(data);
info.setLimit(limit);
info.setTotalPage(totalPage);
info.setCount(count);
return info;
}
protected String trimSql(String sql) {
if(sql.endsWith("and")) {
int andIndex = sql.lastIndexOf("and");
sql = sql.substring(0, andIndex);
} else if(sql.endsWith("where")) {
int whereIndex = sql.lastIndexOf("where");
sql = sql.substring(0, whereIndex);
}
return sql;
}
/*计算满足条件的数据一共有多少条*/
private int countPage(String sql, Connection conn) throws SQLException {
int fromIndex = sql.indexOf("from");
sql = sql.substring(fromIndex);
String countSql = "select count(1) " + sql;
PreparedStatement ps = conn.prepareStatement(countSql);
ResultSet rs = ps.executeQuery();
rs.next();
int count = rs.getInt(1);
ConnPool.realse(rs, ps);
return count;
}
}
DaoImpl实现类
这一层比较特殊,不仅实现了Dao层接口,并且还继承了BaseDao抽象类,这样实现类不仅实现了Dao接口方法,并且可以直接调用父类的方法,而不需要以构造器传实参的方式调用,比较调用起来会比较简单。
public class UserDaoImpl extends BaseDao implements UserDao{
ConnPool connPool = new ConnPool();
@Override
public PageQueryInfo listUsers(Map<String, Object> params) {
Connection conn = connPool.getConnection();
String sql = "select id as id, user_name as userName, password as password, real_name as realName from u_user where";
if(!CheckParamUtil.isBlank(params.get("userName"))) {
sql += " user_name like '" + params.get("userName") + "%' and";
}
if(!CheckParamUtil.isBlank(params.get("realName"))) {
sql += " real_name like '" + params.get("realName") + "%' and";
}
sql = this.trimSql(sql);//这里的this调用的是BaseDao中封装的方法,主要是为了将where和and截取掉
Object pageNo = params.get("page");
Object size = params.get("limit");
int currentPage = 1;
int limit = 10;
if(!CheckParamUtil.isBlank(pageNo)) {
currentPage = Integer.parseInt(""+pageNo);
}
if(!CheckParamUtil.isBlank(size)) {
limit = Integer.parseInt(""+ size);
}
try {
PageQueryInfo pageInfo = this.queryPage(currentPage, limit, sql, User.class, conn);
return pageInfo;
} catch (SQLException e) {
e.printStackTrace();
} finally {
connPool.realse(conn);
}
return new PageQueryInfo();
}
@Override
public boolean addUser(User user) throws SQLException {
Connection conn = connPool.getConnection();
Boolean flag = this.addData(conn, user);
connPool.realse(conn);
if(flag) {
return true;
}
return false;
}
@Override
public boolean delUser(List<Integer> ids) {
Connection conn = connPool.getConnection();
Boolean flag = this.deleteData(conn, "u_user", "id", ids);
connPool.realse(conn);
if(flag) {
return true;
}
return false;
}
@Override
public User queryById(int id) {
Connection conn = connPool.getConnection();
String sql = "select id as id, user_name as userName, password as password, real_name as realName from u_user where id = ?";
List<User> users = this.queryData(conn, User.class, sql, id);
connPool.realse(conn);
return users.size() > 0 ? users.get(0) : null;
}
@Override
public boolean editUser(User user) throws SQLException {
Connection conn = connPool.getConnection();
String sql = "update u_user set user_name = ?,password = ?, real_name = ? where id= ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, user.getUserName());
ps.setString(2, user.getPassword());
ps.setString(3, user.getRealName());
ps.setInt(4, user.getId());
if(ps.executeUpdate() > 0) {
connPool.realse(conn);
return true;
}
connPool.realse(conn);
return false;
}
}
以上的代码是UserDao的实现类,CustomerDao的实现类的方法也都大同小异,大家就当练手,可以自己尝试写出来。ContractDao的实现类就不太一样了,它涉及到了三表联合查询,还是上代码
public class ContractDaoImpl extends BaseDao implements ContractDao {
ConnPool connPool = new ConnPool();
@Override
public PageQueryInfo listContracts(Map<String, Object> params) {
Connection conn = connPool.getConnection();
String sql = "select ct.id as id, cc.cust_name as custName,cc.id as custId, uu.real_name as saleName, uu.id as saleId, ct.content as content, date_format(ct.create_time,'%Y-%m-%d') as createTime from u_user uu, c_customer cc, c_contract ct where uu.id = ct.sale_id and ct.cust_id = cc.id ";
if(!CheckParamUtil.isBlank(params.get("saleName"))) {
sql += "and uu.real_name like '" + params.get("saleName") + "%' and";
}
if(!CheckParamUtil.isBlank(params.get("custName"))) {
sql += "and cc.cust_name like '" + params.get("custName") + "%' and";
}
if(!CheckParamUtil.isBlank(params.get("startDate"))) {
sql += "and ct.create_time >= '" + params.get("startDate") + "' and";
}
if(!CheckParamUtil.isBlank(params.get("endDate"))) {
sql += " ct.create_time < '" + params.get("endDate") + "' and";
}
sql = this.trimSql(sql);//这里的this调用的是BaseDao中封装的方法,主要是为了将where和and截取掉
Object pageNo = params.get("page");
Object size = params.get("limit");
int currentPage = 1;
int limit = 10;
if(!CheckParamUtil.isBlank(pageNo)) {
currentPage = Integer.parseInt(""+pageNo);
}
if(!CheckParamUtil.isBlank(size)) {
limit = Integer.parseInt(""+ size);
}
try {
PageQueryInfo pageInfo = this.queryPage(currentPage, limit, sql, ContractVO.class, conn);
return pageInfo;
} catch (SQLException e) {
e.printStackTrace();
} finally {
connPool.realse(conn);
}
return new PageQueryInfo();
}
@Override
public boolean addContract(Contract contract) throws SQLException {
Connection conn = connPool.getConnection();
Boolean flag = this.addData(conn, Contract.class);
connPool.realse(conn);
if(flag) {
return true;
}
return false;
}
@Override
public boolean delContract(List<Integer> ids) throws SQLException {
Connection conn = connPool.getConnection();
Boolean flag = this.deleteData(conn, "c_contract", "id", ids);
connPool.realse(conn);
if(flag) {
return true;
}
return false;
}
}
那么Dao层就讲到这儿,下一节我们继续完善我们的Service层