- 浏览: 17583 次
- 性别:
- 来自: 上海
最新评论
-
指甲刀X:
关于最后的问题,个人认为不管内部函数是否访问外层定义的变量,都 ...
Javascript的作用域,闭包的真正含义 -
liushian:
附件根本不是示例代码,是dbutil的源代码
dbutils使用示例代码 -
王世伟:
一个老师可以教多个班级,但是一个班级也可以被多个老师教啊?所以 ...
数据库表之间的关联关系 -
kanny87929:
zhouxingfu520 写道怎么我情况和你差不多 公司两 ...
(模板方法的运用)持久层操作的java代码 -
zhouxingfu520:
怎么我情况和你差不多 公司两人搞java 其他都是.net
(模板方法的运用)持久层操作的java代码
2008年刚从学校毕业就应聘到了一家外包小公司工作
对加拿大的客户开发一些web项目
公司里算我就2个人是做java的
于是我们变成了一个人身兼数个项目的程序员
经理只给我们客户的需求
然后数据库设计、编码等事你一个人搞定。。。
我当时刚出来对java的理解还没有那么深,没有商业项目的任何经验就让我搞着搞那。
当时连数据库连接的操作我都很苦恼,是用简单的jdbc还是hibernate呢,
最后为了方便而达到目的我选用了前者。赶项目的效率还是很重要的。
我给出当时自己写的操作数据库的代码
这家公司大多都是.net的程序所以用的数据库也为sql server 2005
所以不知道这样写是不是会有很多问题,因为我总觉得有问题。
3年后虽然已经离开公司但再回头看这些代码,我还是觉得有问题,所以必须发出来大家审视一下。
这些代码是2008年4月刚出道时自己写的。当时正在读老师推荐给我的java设计模式,看到了template这个模式,于是在工作中突然想到可以把这个模式应用在操作数据库的代码上
于是就产生了以下代码。
第一个是操作数据库方法的抽象接口,
其实这个接口也很简单,定义了那么几个方法,说白了就是操作数据库的。
为什么要写成泛型的接口,为了就是后面大家的业务有针对性,一个实体一个业务功能类。
package com.yd.idao; import java.util.List; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import com.yd.support.JDataSet; /** * 一个定义了所有我所需要的数据库操作的方法接口, * 为什么定义为抽象,我自己都搞不清楚, * 这里定义了泛型,这个很关键,你会看到泛型在这里的使用 * @author kanny * * @param <T> */ public abstract interface ISqlHelper<T> { /** * 执行sql语句,大多为单句插入语句 * @param sql 单句的sql语句 * @param params 插入的参数 * @param only 但为true时,sql语句为查询数量的查询语句 * @return * @throws SQLException */ public boolean execute(String sql, Object[] params, boolean only) throws SQLException; /** * 执行sql的批处理 * @param sqlBatch 多条sql语句 * @return * @throws SQLException */ public boolean executeBatch(String[] sqlBatch) throws SQLException; /** * 执行存储过程 * @param procName 存储过程名称 * @param params 存储过程说需要的参数 * @return * @throws SQLException */ public boolean executeCall(String procName, Object[] params) throws SQLException; /** * 查询一行数据封装成java的实体 * @param sql sql语句 * @param params sql条件参数 * @param viewName 视图名字,在查询多表关联的数据时用于区分 * @param executeCall 是否是存储过程,如果为true,第一个sql的参数为存储过程名称 * @return * @throws SQLException */ public T find(String sql, Object[] params, String viewName, boolean executeCall) throws SQLException; /** * 查询多行数据封装成java的实体加入一个List里 * @param sql sql语句 * @param params sql条件参数 * @param viewName 视图名字,在查询多表关联的数据时用于区分,循环封装实体比单一的石头封装要复杂 * @param executeCall 是否是存储过程,如果为true,第一个sql的参数为存储过程名称 * @return * @throws SQLException */ public List<T> findList(String sql, Object[] params, String viewName, boolean executeCall) throws SQLException; /** * 为了方便操作,我还特意写定义了这个返回ResultSet的方法,便于直接操作 * @param sql * @param params * @param executeCall * @return * @throws SQLException */ public ResultSet returnResultSet(String sql, Object[] params, boolean executeCall) throws SQLException; /** * 我的底层分页方法,我会给出具体代码,但这里用的只是sql server 2008的数据库分页 * @param sql * @param orderby 排序列 * @param currentPage 当前页 * @param pageSize 每页多少行 * @return * @throws SQLException */ public List<T> findListAsPager(String sql, String orderby, int currentPage, int pageSize) throws SQLException; /** * 后来为了方便操作,想朋友要来了这个JDataSet类,类似.net的DataTable的作用 * @param sql * @param params * @param fillColumnNames 是否填充类名,请看方法代码 * @param executeCall * @return */ public JDataSet getJDataSet(String sql, Object[] params, boolean fillColumnNames, boolean executeCall); /** * 由于有了JDataSet这个类,于是我有写了调用这个类的分页方法 * @param sql * @param orderby * @param currentPage * @param pageSize * @return * @throws SQLException */ public JDataSet getJDataSetAsPager(String sql, String orderby, int currentPage, int pageSize) throws SQLException; /** * 为了方便起见,我多写了一个直接传入ResultSet而封装JDataSet的多余方法 * @param rs * @param fillColumnNames * @return * @throws SQLException */ public JDataSet loadJDataSet(ResultSet rs, boolean fillColumnNames) throws SQLException; /** * 得到查询数据的行数 * @param sql * @return * @throws SQLException */ public int getRowCount(String sql) throws SQLException; /** * 请看源码 * @param rs * @param column * @return * @throws SQLException */ public String changeFont(ResultSet rs, String column) throws SQLException; /** * 得到连接 * @return * @throws SQLException */ public Connection returnConn() throws SQLException; /** * 清楚所有数据库操作对象 * @throws SQLException */ public void clearAllsql() throws SQLException; }
第2个类是实现这个抽象接口的抽象模版方法类
这个类最为关键,它肯定是实现了ISqlHepler.java里面的所有的方法。
其中:
protected abstract T loadDataBean(ResultSet rs, String viewName) throws SQLException;
protected abstract T loadDataBeanSelf(ResultSet rs) throws SQLException;
这2个方法是SqlHelper.java里留出来了,就是为了大家可以自己封装实体javabean来用
package com.yd.dao; import java.sql.*; import java.util.*; import com.yd.db.DBConnPoolMgr; import com.yd.idao.ISqlHelper; import com.yd.support.JDataSet; public abstract class SqlHelper<T> implements ISqlHelper<T> { protected java.sql.Connection conn = null; protected java.sql.PreparedStatement pst = null; protected java.sql.Statement st = null; protected java.sql.CallableStatement cs = null; protected java.sql.ResultSet rs = null; protected java.sql.ResultSetMetaData rm = null; public Connection returnConn() throws SQLException { //DBConnPoolMgr是自己写的一个简单连接池类,用来得到连接,我后面会给出这个类的代码 return (conn = DBConnPoolMgr.getInctence().getConnect()); } private PreparedStatement returnPst(String sql, Object[] params) throws SQLException { if (conn == null || conn.isClosed()) conn = returnConn(); pst = conn.prepareStatement(sql); if (params != null) for (int i = 0; i < params.length; i++) pst.setObject(i + 1, params[i]); return pst; } protected CallableStatement returnCs(String procName, Object[] params) throws SQLException { if (conn == null || conn.isClosed()) conn = returnConn(); String call = ""; if (params != null) { call = "{call " + procName + "("; for (int c = 0; c < params.length - 1; c++) call += "?,"; call += "?)}"; } else call = "{call " + procName + "()}"; cs = conn.prepareCall(call); if (params != null) for (int i = 0; i < params.length; i++) cs.setObject(i + 1, params[i]); return cs; } public void clearAllsql() { try { if (rs != null) rs.close(); if (cs != null) cs.close(); if (st != null) st.close(); if (pst != null) pst.close(); if (conn != null) { DBConnPoolMgr.getInctence().returnConnect(conn); } rs = null; cs = null; st = null; pst = null; } catch (SQLException ex) { ex.printStackTrace(); } } public boolean execute(String sql, Object[] params, boolean only) { boolean bVal = false; try { if (only) { rs = returnPst(sql, params).executeQuery(); while (rs.next()) bVal = true; } else { returnPst(sql, params).executeUpdate(); bVal = true; } } catch (SQLException ex) { ex.printStackTrace(); } finally { clearAllsql(); } return bVal; } public boolean executeBatch(String[] sqlBatch) { boolean bVal = false; try { conn = returnConn(); st = conn.createStatement(); boolean autoCommit = conn.getAutoCommit(); for (int i = 0; i < sqlBatch.length; i++) { if (sqlBatch[i] != null && !sqlBatch[i].equals("")) st.addBatch(sqlBatch[i] + ";"); } conn.setAutoCommit(false); st.executeBatch(); conn.commit(); conn.setAutoCommit(autoCommit); bVal = true; } catch (SQLException ex) { try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } ex.printStackTrace(); } finally { clearAllsql(); } return bVal; } public boolean executeCall(String procName, Object[] params) { boolean bVal = false; try { returnCs(procName, params).executeUpdate(); bVal = true; } catch (Exception ex) { ex.printStackTrace(); } finally { clearAllsql(); } return bVal; } public T find(String sql, Object[] params, String viewName, boolean executeCall) { T t = null; try { if (executeCall) rs = returnCs(sql, params).executeQuery(); else rs = returnPst(sql, params).executeQuery(); t = loadResultSet(rs, viewName); } catch (Exception ex) { ex.printStackTrace(); } finally { clearAllsql(); } return t; } public List<T> findList(String sql, Object[] params, String viewName, boolean executeCall) { List<T> lt = null; try { if (executeCall) rs = returnCs(sql, params).executeQuery(); else rs = returnPst(sql, params).executeQuery(); lt = loadList(rs, viewName); } catch (Exception ex) { ex.printStackTrace(); } finally { clearAllsql(); } return lt; } public ResultSet returnResultSet(String sql, Object[] params, boolean executeCall) { try { if (executeCall) rs = returnCs(sql, params).executeQuery(); else rs = returnPst(sql, params).executeQuery(); } catch (Exception ex) { ex.printStackTrace(); } return rs; } private T loadResultSet(ResultSet rs, String viewName) throws SQLException { T t = null; if (rs != null) while (rs.next()) t = loadDataBean(rs, viewName); return t; } private List<T> loadList(ResultSet rs, String viewName) throws SQLException { List<T> tlist = new ArrayList<T>(); if (rs != null) while (rs.next()) tlist.add(loadDataBean(rs, viewName)); return tlist; } public String changeFont(ResultSet rs, String column) throws SQLException { return rs.getString(column) == null ? "" : rs.getString(column); } public int returnColumnCount(ResultSet rs) throws SQLException { return rs.getMetaData().getColumnCount(); } //两个非常关键的模版方法,继承此类的操作类都要实现这2个方法,我到时候会给出操作类 protected abstract T loadDataBean(ResultSet rs, String viewName) throws SQLException; protected abstract T loadDataBeanSelf(ResultSet rs) throws SQLException; public List<T> findListAsPager(String sql, String orderby, int currentPage, int pageSize) { List<T> lt = null; try { String strVal = strPager(sql, orderby, currentPage, pageSize); rs = returnPst(strVal, null).executeQuery(); lt = loadList(rs, ""); } catch (SQLException ex) { ex.printStackTrace(); } finally { clearAllsql(); } return lt; } //因为用的sql server 2008所以只写了这个数据库的分页 private String strPager(String sql, String orderby, int currentPage, int pageSize) { int start = 1; if (currentPage > 1) start = (currentPage - 1) * pageSize + 1; int end = start + pageSize - 1; String sqlColumn = "*"; String sqlDo = ""; if(sql.indexOf("@#") != -1) { String []sqlArr = sql.split("@#"); sqlColumn = sqlArr[0]; sqlDo = sqlArr[1]; } else { sqlColumn = "*"; sqlDo = sql; } String strVal = "select * from (select " + sqlColumn + ",ROW_NUMBER()"; strVal += " Over(order by " + orderby + ")"; strVal += " as rowNum " + sqlDo + ")"; strVal += " as myTable where rowNum between " + start + " and " + end; return strVal; } public int getRowCount(String sql) throws SQLException { String sqlDo = ""; if(sql.indexOf("@#") != -1) { String []sqlArr = sql.split("@#"); sqlDo = sqlArr[1]; } else sqlDo = sql; int count = 0; try { rs = this.returnResultSet("select count(*) " + sqlDo, null, false); while (rs.next()) count = rs.getInt(1); } catch (Exception ce) { ce.printStackTrace();} finally { clearAllsql(); } return count; } public JDataSet getJDataSetAsPager(String sql, String orderby, int currentPage, int pageSize) { String strVal = strPager(sql, orderby, currentPage, pageSize); return getJDataSet(strVal, null, true, false); } public JDataSet getJDataSet(String sql, Object[] params, boolean fillColumnNames, boolean executeCall) { JDataSet jds = null; try { if (executeCall) rs = returnCs(sql, params).executeQuery(); else rs = returnPst(sql, params).executeQuery(); jds = loadJDataSet(rs, fillColumnNames); } catch (Exception ex) { ex.printStackTrace(); } finally { clearAllsql(); } return jds; } public JDataSet loadJDataSet(ResultSet rs, boolean fillColumnNames) { JDataSet jds = new JDataSet(); try { int columnCount = returnColumnCount(rs); if (fillColumnNames) { String[] columnNames = new String[columnCount]; String[] columnTypeNames = new String[columnCount]; for (int i = 0; i < columnCount; i++) { columnNames[i] = rs.getMetaData().getColumnName(i + 1); columnTypeNames[i] = rs.getMetaData().getColumnTypeName(i + 1); } jds.setColumnNames(columnNames); jds.setColumnTypeNames(columnTypeNames); } while (rs.next()) { String[] row = new String[columnCount]; for (int i = 0; i < columnCount; i++) row[i] = rs.getString(i + 1) == null ? "" : rs.getString(i + 1).trim(); jds.addRow(row); } } catch (Exception ex) { ex.printStackTrace(); } return jds; } }
现在来说下怎么用这个类
比如,你有一个学生类Student.java里面有id,name,age3个属性
public Class Student { private int id; private String name; private int age; 以下get和set方法省略... }
你要封装它,你就可以自己定义一个IStudent.java接口extends那个ISqlHelper.java接口
然后来里面定义插入,查询全部,和按id查的功能函数,象如下写的一样
<
当然这样定义很死,最好的方法,就是整理抽象出所有业务类的公用方法,比如,插入,修改,删除。
然后把这些方法在一个公用的操作接口中定义,这个公用的操作接口可以继承ISqlHelper.java接口
然后以后业务类或是数据实体操作类都可以实现这个公用的操作接口。
>
public interface IStudent extends ISqlHelper<Student> { //插入Student public boolean insertStudent(Student stu); //查询全部Student public List<Student> findStudent(); //按id查询某一个Student public Student findStudentAsId(int stuid); }
并写一个StudentBO.java业务类extends那个SqlHelper和自己定义的IStudent接口
象如下写的一样:
public Class StudentBO extends SqlHelper<Student> implements IStudent { protected Student loadDataBean(ResultSet rs, String viewName) throws SQLException; { Student stu = loadDataBeanSelf(ResultSet rs); return stu; } protected Student loadDataBeanSelf(ResultSet rs) throws SQLException; { Student stu = new Student(); stu.setId(rs.getInt("id")); stu.setName(rs.changeFont(rs,"name")); stu.setAge(rs.getInt("age")); return stu; } //实现:插入Student的函数 public boolean insertStudent(Student stu) { String sql = "insert into Student(id,name,age) values(?,?,?)"; Object [] params = new Object[]{stu.getId(),stu.getName,stu.getAge}; return this.execute(sql, params, false); } //实现:查询全部Student public List<Student> findStudent() { String sql = "select * from Student"; return this.findList(sql, null, "",false); } //实现:按id查询某一个Student public Student findStudentAsId(int stuid) { String sql = "select * from Student where id=" + stuid; return this.find(sql, null, "",false); } }
loadDataBean,loadDataBeanSelf是从SqlHelper里继承下来的抽象方法。
必须实现。这就是利用了模版方法模式写出来的。
也就是说,以后你自己写函数的时候,只要在接口里定义,
然后在这样的BO类里写实现它,而且就写那么一点语句就完成了。大大省时省力。
好了这样就完成了,代码是不是看上去又清楚又整洁,如果查找和维护。而且大大减少了那些功能代码和封装象Student.java这样数据实体的代码。一次封装无须在写。
大家肯定有疑问,那就是
this.execute
this.findList
this.find
三个函数哪来的,里面都做了些什么
首先要说他们3个肯定是SqlHelper里被实现过的函数
至于他们怎么实现的,你仔细看下就全明白了。
为什么要多出一个loadDataBean来,大家都看到了,他有一个参数viewName,这里就是用到这个参数的地方,因为大家操作数据库不可能就是那么一张表的操作,有时候会有2到3张表联查,那么用这个参数来判断是哪个函数查出不一样的结果,那么你在这个函数里利用这个参数引进别的xxxBO的loadDataBeanSelf函数,不就可以不用再次重新写那些讨厌的实体封装代码了吗。重用性大大提升。
注意一点,这里的查询是只能全查,如果只需要几个字段,就只能手动自己写咯,其实我是想写一个通用的想查几个字段就几个字段的封装方法,但我懒,所以到现在都没去写
其实还有很多应用和问题,这些我在这里也说不完,希望大家多多交流。
我还会给出我自己当初写的数据库连接池类,希望这些简单的代码能给java新手以帮助。
而且如果大家觉得有问题有意义,一定要发帖指出。哪里好哪里不好
希望大家多多给出看法,多多益善。
在这里还要感谢论坛中yangguo兄,其实我当时写这段代码的主要目的
就是dbutils框架所实现的一个最重要功能
只提交sql语句,然后的数据自动填充到所需要的实体中。而不要在写那么多繁琐的实体封装代码。
这个是源码例子,希望大家能明白这样写的用意,值得探讨。
- Demo.rar (341.4 KB)
- 下载次数: 486
评论
89 楼
kanny87929
2011-06-23
zhouxingfu520 写道
怎么我情况和你差不多 公司两人搞java 其他都是.net
很多公司都是这个情况
88 楼
zhouxingfu520
2011-06-22
怎么我情况和你差不多 公司两人搞java 其他都是.net
87 楼
chakey
2011-05-27
刚出道 就能写这么好质量的代码 很厉害了
86 楼
kanny87929
2011-05-26
日照西桥 写道
我也要赞一下楼主
不错啊,第一篇文章写我这里了
85 楼
日照西桥
2011-05-25
我也要赞一下楼主
84 楼
kanny87929
2011-04-21
doublelcf 写道
真的写的不错,java思想很重要,有思想才产生出作品
这帖子又跳起来了
83 楼
doublelcf
2011-04-21
真的写的不错,java思想很重要,有思想才产生出作品
82 楼
kanny87929
2011-04-07
Speak-shuai 写道
lz太牛了
谢谢赞赏。。。。
81 楼
Speak-shuai
2011-04-07
lz太牛了
80 楼
kanny87929
2011-04-07
yjp0501 写道
我现在写的都只是这样呢,呵呵,其实我现在才出来,大学都还没有毕业呢,追赶中!!!
这里主要的思想体现的模板方法模式的运用。这个才是关键,如果只是把这些代码整理到一个类里意义就不大了
79 楼
kanny87929
2011-04-07
c267ray 写道
kanny87929 写道
lgm277531070 写道
68.
69. /**
70. * 为了方便操作,我还特意写定义了这个返回ResultSet的方法,便于直接操作
71. * @param sql
72. * @param params
73. * @param executeCall
74. * @return
75. * @throws SQLException
76. */
77. public ResultSet returnResultSet(String sql, Object[] params, boolean executeCall) throws SQLException;
我被这个雷到了,还能返回ResultSet结果集?????
那方法里面的结果集你没关闭么???如果关闭了,还怎么能返回呢???
69. /**
70. * 为了方便操作,我还特意写定义了这个返回ResultSet的方法,便于直接操作
71. * @param sql
72. * @param params
73. * @param executeCall
74. * @return
75. * @throws SQLException
76. */
77. public ResultSet returnResultSet(String sql, Object[] params, boolean executeCall) throws SQLException;
我被这个雷到了,还能返回ResultSet结果集?????
那方法里面的结果集你没关闭么???如果关闭了,还怎么能返回呢???
这个方法的ResultSet对象,是没有关闭的,所以要在自己的方法里自行关闭。
是否可以参考CachedRowSet?
有机会我会去看
78 楼
yjp0501
2011-04-06
我现在写的都只是这样呢,呵呵,其实我现在才出来,大学都还没有毕业呢,追赶中!!!
77 楼
c267ray
2011-04-06
kanny87929 写道
lgm277531070 写道
68.
69. /**
70. * 为了方便操作,我还特意写定义了这个返回ResultSet的方法,便于直接操作
71. * @param sql
72. * @param params
73. * @param executeCall
74. * @return
75. * @throws SQLException
76. */
77. public ResultSet returnResultSet(String sql, Object[] params, boolean executeCall) throws SQLException;
我被这个雷到了,还能返回ResultSet结果集?????
那方法里面的结果集你没关闭么???如果关闭了,还怎么能返回呢???
69. /**
70. * 为了方便操作,我还特意写定义了这个返回ResultSet的方法,便于直接操作
71. * @param sql
72. * @param params
73. * @param executeCall
74. * @return
75. * @throws SQLException
76. */
77. public ResultSet returnResultSet(String sql, Object[] params, boolean executeCall) throws SQLException;
我被这个雷到了,还能返回ResultSet结果集?????
那方法里面的结果集你没关闭么???如果关闭了,还怎么能返回呢???
这个方法的ResultSet对象,是没有关闭的,所以要在自己的方法里自行关闭。
是否可以参考CachedRowSet?
76 楼
kanny87929
2011-04-06
shansun123 写道
嗯嗯 刚出道就能写出这么漂亮的代码 值得赞~!
谢楼上称赞
75 楼
shansun123
2011-04-06
嗯嗯 刚出道就能写出这么漂亮的代码 值得赞~!
74 楼
kanny87929
2011-04-06
zhangwe415 写道
好吧!我没承认没好好学习,现在来学习你的。楼主有什么学习经验推荐没,项目上学习的东西有限,主要想自己发展!
我现在学习的目标只集中在
原代码和数据结构和算法上
原代码,看的项目是dbutils1.3和tomcat5.5和7,还下载了lucene不过我估计看不到最近
还有就是基础
java.lang下的各类,Object, Class
java.util下的各个工具类,比如ArrayList和HashMap
java.io各个类的实现
数据结构和算法上我看的是
java数据结构和算法的第2版
这个很有意义,以后我肯定会把各种算法用java整理出来发布在论坛
73 楼
zhangwe415
2011-04-06
好吧!我没承认没好好学习,现在来学习你的。楼主有什么学习经验推荐没,项目上学习的东西有限,主要想自己发展!
72 楼
kanny87929
2011-04-06
linluvsls 写道
我也刚出道 偶杂就写不出来·······
也许你没有好好学习
71 楼
linluvsls
2011-04-06
我也刚出道 偶杂就写不出来·······
70 楼
kanny87929
2011-04-05
ekian 写道
刚出道已有这功力了。。LZ这是多久的积累啊?
没工作前一直在看设计模式,工作了就非常想把自己唯一看明白的几个模式运用带项目中,于是就有了这些代码的设计
相关推荐
在Java Web开发中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。其中,反向工程(Reverse Engineering)是Hibernate提供的一项功能,它能根据数据库结构自动生成对应的Java实体类、...
《持久层用户开发手册》是中国软件与技术服务股份有限公司应用产品研发中心提供的一份详细的技术文档,旨在帮助开发者理解和使用持久层进行数据库操作。手册的核心内容涵盖了持久层的基本概念、设计目标、开发流程、...
MyBatis则是一个持久层框架,它将SQL语句与Java代码分离,提供了更加灵活的数据库操作方式。 此外,开发过程中还需要注意前端技术的运用,比如Bootstrap是一个流行的CSS框架,用于创建响应式布局和移动设备优先的...
MyBatis是一个持久层框架,它简化了SQL操作,允许开发者直接编写SQL语句,将数据库操作与业务逻辑分离。在Java考勤系统中,MyBatis作为数据访问层,用于执行SQL查询,实现对考勤数据的增删改查操作。 **4. Maven...
- **生成Mapper接口**:为每个表生成相应的Mapper接口,包含基本的CRUD操作方法。 - **生成XML映射文件**:生成与Mapper接口相对应的XML配置文件,定义SQL语句和结果映射。 ### 3. 运行流程 1. **配置...
5. **持久层框架**:如Hibernate和MyBatis,它们帮助开发者更方便地操作数据库,减少手写SQL,提高开发效率。了解这些框架的优缺点以及如何集成到项目中是关键。 6. **分布式系统**:包括负载均衡、集群、分布式...
- **导入模块**: 这部分代码负责接收用户上传的Excel文件,解析数据,校验格式,然后将数据存储到数据库或其他持久化层。 - **导出模块**: 用户可以根据特定条件请求导出数据,此时服务会查询数据库,将数据填充到...
【Java简历模板详解】 在Java开发领域,一份详尽的简历是展示个人技能和经验的重要途径。本简历的主人公王鹏是一名经验丰富的Java开发工程师,他的技能和经历涵盖了多个方面,包括基础编程、Web开发、ORM框架、...
JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...
Springboot集成的MyBatis或JPA等持久层框架,用于处理数据库操作。在本项目中,数据库的设计与管理至关重要,因为它存储了所有教务信息,如课程安排、学生信息、教师信息等。数据库设计应遵循关系数据库的规范,确保...
- **JVM(Java虚拟机)**:Java代码需要通过JVM转换为机器码运行,实现“一次编写,到处运行”。 2. **Struts框架** - **MVC模式**:Struts将Web应用分为模型、视图和控制器三个部分,使得各部分职责明确,降低...
JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...
"java web开发简历模板【精选文档】" 以下是根据给定的文件信息生成的相关知识点: Java 基础 * 熟练使用 Java 语言进行编程开发 * 对 core Java 有较好的理论基础 * 精通流程控制、多种数据结构、排序算法等 * ...
4. **MyBatis**:MyBatis是一个持久层框架,它简化了数据库访问,通过XML或注解配置来映射原生信息,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。在本项目中,MyBatis可能...
综上所述,"FreeMarker 生成Java、mybatis文件"是一个利用FreeMarker模板引擎自动化生成Java代码和MyBatis XML配置文件的过程。通过理解和运用这一技术,开发者可以提升工作效率,同时保证代码质量。
- **MyBatis**: 数据持久层框架,用于处理数据库操作,通过XML或注解方式将SQL与Java代码绑定,简化了数据访问。 - **Thymeleaf**: 前端模板引擎,用于动态生成HTML页面,与Spring Boot结合使用,提供便捷的MVC...
8. **模板引擎**: 为了快速生成动态HTML,可能使用FreeMarker或Thymeleaf等模板引擎,它们允许开发者用Java代码控制HTML结构。 9. **单元测试与集成测试**: 使用JUnit或TestNG进行单元测试,验证每个函数或类的正确...
- **MyBatis**: 作为持久层框架,它简化了数据库操作,使得SQL与Java代码更好地解耦。 - **Maven**: 项目管理和构建工具,用于自动化构建、依赖管理和项目信息管理。 2. **项目结构**: - `sci_mgr-master`目录...
Spring提供了依赖注入(DI)和面向切面编程(AOP),SpringMVC用于处理Web层逻辑,而Hibernate则是持久层的解决方案,负责数据库操作。下面将详细阐述这三个框架及其在模板中的应用。 1. **Spring框架**:Spring是...