JDBC模板类实现(version1.1)

本文介绍了一种通过模板类简化JDBC编程的方法,该方法能够减少重复代码并提高开发效率。文章详细展示了如何创建一个DAO模板类,用于统一处理数据库连接获取、释放等常见任务。
package daoUtil.daoTemplate;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;

import jdbcUtil.JdbcUtil;
import daoUtil.PrimaryKeyer;
import daoUtil.RowMapper;
/**
 * 在写jdbc程序是可以清楚的知道
 * 在程序中只有sql语句和其参数值是变化
 * 其余程序代码几乎类似(获得连接,关闭连接)
 * 在这里我对以前所写jdbc程序进行了一下改进
 * 将获得连接和关闭连接的程序代码交给一个模板类去做
 * 再写jdbc程序时,调用模板类中相应的方法,传入sql语句和其参数值
 * 这样大大简化jdbc程序,给我们带来方便
 * 程序新版本往后日子会不断更新,渴望javaeye里面高手多多给我指点
 * @author kevin.wangwei
 * Email:wanwei.234@163.com
 * 2010-1-30
 */
public class DAOTemplate{
	/**jdbc工具类*/
	private JdbcUtil jdbcUtil=JdbcUtil.getInstance();
	/**
	 * 数据库删除操作
	 * @param sql 删除操作sql语句
	 * @param args 删除操作sql语句参数值数组
	 * @return 删除记录条数
	 * @throws SQLException
	 */
	public  int delete(String sql, Object[] args) throws SQLException {
		if(args==null||args.length==0){
			return 0;
		}
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			conn=jdbcUtil.getConnection();
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1,args[i]);//在这里我们应该调用下面的PreparedStatementSetValue方法,
				                          //不过这样写亦可以,但它不可以处理null值
			}
			return ps.executeUpdate();
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
	}
	/**
	 * 数据库更新操作
	 * @param sql 更新操作sql语句
	 * @param args sql语句参数值数组
	 * @return 更新记录条数
	 * @throws SQLException
	 */
	public int update(String sql, Object[] args) throws SQLException {
		if(args==null||args.length==0){
			return 0;
		}
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			conn=jdbcUtil.getConnection();
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1,args[i]);
			}
			return ps.executeUpdate();
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
	}
	/**
	 * 数据库查询操作 采用反射来给包装sql语句参数赋值
	 * @param sql 查询操作sql语句
	 * @param args 删除操作sql语句数组数值
	 * @return 结果对象
	 * @throws SQLException
	 */
	public Object find(String sql, Object[] args,RowMapper rowMapper) throws SQLException {
		if(args==null||args.length==0){
			return 0;
		}
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			conn=jdbcUtil.getConnection();
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			for(int i=0;i<args.length;i++){
				try {
					PreparedStatementSetValue(ps,args[i],i+1);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			rs=ps.executeQuery();
			Object obj=null;
			while(rs.next()){
				obj=rowMapper.rowMapping(rs);
			}
			return obj;
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
	}

	/**
	 * 获得表中记录数
	 * @param sql sql语句
	 * @param args 参数数组
	 * @return 表中记录数
	 * @throws SQLException
	 */
	public int getRecordCount(String sql, Object[] args) throws SQLException {
		if(args==null||args.length==0){
			return 0;
		}
		int count=0;
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			conn=jdbcUtil.getConnection();
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1,args[i]);
			}
			if(rs.next()){
				count=rs.getInt(1);
			}
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
		return count;
	}
	/**
	 * 根据数据库表名,找到该表中所有记录数
	 * @param tableName 要查询的表
	 * @return 表中记录数
	 * @throws SQLException
	 */
	public int getRecordCount(String tableName) throws SQLException {
		if(tableName==null||tableName.equals("")){
			return 0;
		}
		int count=0;
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			conn=jdbcUtil.getConnection();
			String sql="select count(*) from "+tableName;
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			if(rs.next()){
				count=rs.getInt(1);
			}
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
		return count;
	}
	/**
	 * 数据库插入操作(这是采用接口回调技术,由调用程序来给主键赋值)
	 * @param sql 插入操作 sql语句
	 * @param args 插入数
	 * @param primaryIndex 主键在sql语句中位置(小于-1表示用数据自动生成主键不需要插入)
	 * @return 插入记录数
	 * @throws Exception 
	 */
	public int insert(String sql, Object[] args, int primaryKeyIndex,PrimaryKeyer primaryKeyer) throws Exception {
		if(args==null||args.length==0){
			return 0;
		}
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			conn=jdbcUtil.getConnection();
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			if(primaryKeyIndex<=-1){
				for(int i=0;i<args.length;i++){
					try {
						PreparedStatementSetValue(ps,args[i],i+1);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}else if(primaryKeyIndex>-1&&primaryKeyIndex<args.length){
				for(int i=0;i<args.length;i++){
					if(i==primaryKeyIndex){
						PreparedStatementSetValue(ps,primaryKeyer.getPrimaryKey(),i+1);
						//ps.setObject(i+1,primaryKeyer.getPrimaryKey());
					}else{
						PreparedStatementSetValue(ps,args[i],i+1);
					}
				}
			}else{
				throw new IllegalArgumentException("设置主键位置不正确!");
			}
			return ps.executeUpdate();
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
	}
	/**
	 * 查找符合条件所有记录(这也是采用接口回调技术,由调用程序来决定结果set到什么对象中)
	 * @param sql 查询sql语句
	 * @param args 查询参数
	 * @param rowMapper 结果集映射器
	 * @return Collection 记录集
	 * @throws SQLException
	 */	
	public Collection ObjectList(String sql, Object[] args,RowMapper rowMapper) throws SQLException {
		if(args==null||args.length==0){
			return null;
		}
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		Collection list=null;
		try {
			conn=jdbcUtil.getConnection();
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1,args[i]);
			}
			list=new ArrayList();
			rs=ps.executeQuery();
			while(rs.next()){
				Object obj=rowMapper.rowMapping(rs);
				list.add(obj);
			}
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
		return list;
	}
	/**
	 * 依据与表对应的JavaBean的Class(采用反射技术将结果集set到JavaBean对象中)
	 * 将查询结果封装为一个JavaBean的对象返回
	 * @param sql 查询sql语句
	 * @param args 查询参数
	 * @param javaBeanClass JavaBean的Class
	 * @return 返回获得JavaBean对象
	 * @throws Exception
	 */
	public Object find(String sql, Object[] args,Class javaBeanClass) throws Exception {
		if(args==null||args.length==0){
			return 0;
		}
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			conn=jdbcUtil.getConnection();
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1,args[i]);
			}
			rs=ps.executeQuery();
			String[] names=jdbcUtil.getResultSetFieldName(rs);
			Object obj=null;
			while(rs.next()){
				obj=rowMapper(javaBeanClass,rs,names);
			}
			return obj;
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
	}	
	/**
	 * 依据与表对应的JavaBean的Class(上面方法重载方法,采用了不同实现机制)
	 * 将查询结果封装为一个包含JavaBean的集合对象返回
	 * @param sql 查询sql语句
	 * @param args 查询参数
	 * @param javaBeanClass javaBeanClass JavaBean的Class
	 * @return 记录集
	 * @throws Exception
	 */
	public Collection ObjectList(String sql, Object[] args,Class javaBeanClass) throws Exception {
		if(args==null||args.length==0){
			return null;
		}
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		Collection list=null;
		try {
			conn=jdbcUtil.getConnection();
			ps=jdbcUtil.scrollReadOnlyResultSet(sql,conn);
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1,args[i]);
			}
			list=new ArrayList();
			rs=ps.executeQuery();
			String[] names=jdbcUtil.getResultSetFieldName(rs);
			while(rs.next()){
				Object obj=rowMapper(javaBeanClass,rs,names);
				list.add(obj);
			}
		}finally{
			jdbcUtil.free(rs,ps,conn);
		}
		return list;
	}
	/**
	 * 这个方法是通过反射来将数据库表中对应的javaBean对象set值
	 * 该JavaBean对象必须有一个无参数的构造函数
	 * @param clazz javabean 超类
	 * @param rs 数据库结果集
	 * @return Object 对象
	 * @throws Exception
	 */
	private Object rowMapper(Class clazz,ResultSet rs,String[] names) throws Exception{
		Object obj=clazz.newInstance();
		for(int i=0;i<names.length;i++){
			String columnName=toUpperCaseFirstLetter(names[i]);
			Method[] m=clazz.getMethods();
		    for(int j=0;j<m.length;j++){
				String methodName=m[j].getName();
				if(columnName.equals(methodName)){
					m[j].invoke(obj,rs.getObject(i+1));
					break;
				}
			}
		}
		return obj;
	}
	/**
	 * 将字符串一个字母转换为大写
	 * @param name
	 * @return
	 */
	private String toUpperCaseFirstLetter(String name){
		if(name!=null&&name.length()>0){
			return "set"+name.substring(0,1).toUpperCase()+name.substring(1);
		}
		return "";
	}
	/**
	 * 这是采用反射的方法来给PreparedStatement包装sql 语句参数赋值
	 * @param ps 
	 * @param obj 数组中对象
	 * @param index 参数索引位置
	 * @throws Exception
	 */
	private void PreparedStatementSetValue(PreparedStatement ps,Object obj,int index) throws Exception{
		String name=getMethodName(obj);
		Method[] m=ps.getClass().getMethods();
		for(int i=0;i<m.length;i++){
			String methodName=m[i].getName();
			if(name.equals(methodName)){
				//System.out.println(methodName+"===========");
				m[i].invoke(ps,index,obj);
				break;
			}
		}
		
	}
	/**
	 * 通过反射获得数组中每个元素类型,
	 * 从而获得PreparedStatement对象setxxx方法名称
	 * @param obj  sql语句参数值
	 * @return PreparedStatement对象要调用setxxx方法名称
	 */
	private String getMethodName(Object obj){
		if(obj==null){
			return null;
		}
		String className=obj.getClass().getName();
		String[] names=className.split("\\.");
		className=names[names.length-1];
		if(className.equalsIgnoreCase("Integer")){
			className="Int";
		}
		className="set"+className;
		return className;
	}
}

 

<think>根据用户要求,我们需要将校园信息管理系统需求分析文档(学生填写版)的实现分为三类。结合用户提供的引用内容和之前的讨论,这三类可以理解为: 1. **系统架构与技术实现类**:包含系统整体设计、技术选型、核心架构等 2. **功能模块与业务逻辑类**:包含具体功能实现、CRUD操作、业务规则等 3. **安全与扩展性类**:包含权限管理、系统安全、性能优化等 下面按照这三个类别,用Java实现相关要求: ### 一、系统架构与技术实现类 #### 1.1 技术选型 采用Spring Boot + MyBatis框架实现B/S架构系统[^2],数据库使用MySQL 8.0,前端使用Thymeleaf + Bootstrap 5。 #### 1.2 核心架构设计 ```java // 主应用类 @SpringBootApplication public class CampusInfoSystemApp { public static void main(String[] args) { SpringApplication.run(CampusInfoSystemApp.class, args); } } // 分层架构 - controller (表现层) - service (业务逻辑层) - dao (数据访问层) - entity (实体层) ``` #### 1.3 数据库配置 ```java # application.properties spring.datasource.url=jdbc:mysql://localhost:3306/campus_db?useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver mybatis.mapper-locations=classpath:mapper/*.xml ``` ### 二、功能模块与业务逻辑类 #### 2.1 学生信息管理模块 ```java // 实体类(体现继承关系) @MappedSuperclass public abstract class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String number; // 学号/工号 private String name; private int age; // getters/setters } @Entity @Table(name = "students") public class Student extends Person { private String className; private double score; // 业务规则校验 public void setScore(double score) { if (score < 0 || score > 100) { throw new IllegalArgumentException("成绩必须在0-100之间"); } this.score = score; } } // CRUD服务实现 @Service public class StudentServiceImpl implements StudentService { @Autowired private StudentRepository repository; @Override public Student addStudent(Student student) { // 学号唯一性校验 if (repository.existsByNumber(student.getNumber())) { throw new DuplicateKeyException("学号已存在"); } return repository.save(student); } } ``` #### 2.2 教师信息管理模块 ```java @Entity @Table(name = "teachers") public class Teacher extends Person { private String subject; private BigDecimal salary; public void setSalary(BigDecimal salary) { if (salary.compareTo(BigDecimal.ZERO) < 0) { throw new IllegalArgumentException("薪资不能为负数"); } this.salary = salary; } } ``` ### 三、安全与扩展性类 #### 3.1 RBAC权限管理 ```java // 权限枚举 public enum Permission { STUDENT_VIEW, STUDENT_EDIT, TEACHER_VIEW, TEACHER_EDIT, ADMIN_DASHBOARD } // Spring Security配置 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/students/**").hasAnyAuthority("STUDENT_EDIT") .antMatchers("/teachers/**").hasAnyAuthority("TEACHER_EDIT") .anyRequest().authenticated(); } } ``` #### 3.2 性能优化 ```java // 使用二级缓存提升查询性能 @Cacheable(value = "students", key = "#id") public Student getStudentById(Long id) { return repository.findById(id).orElse(null); } // 批量插入优化 @Transactional public void batchInsertStudents(List<Student> students) { jdbcTemplate.batchUpdate("INSERT INTO students (...) VALUES (...)"); } ``` ### 文档结构实现 ```java // 自动生成需求文档工具类 public class DocumentGenerator { public void generateDoc(String templatePath, Map<String, Object> data) { // 使用Freemarker模板引擎生成Word文档 Configuration cfg = new Configuration(Configuration.VERSION_2_3_30); cfg.setClassForTemplateLoading(this.getClass(), "/templates"); Template template = cfg.getTemplate("requirement_template.ftl"); try (Writer writer = new FileWriter("校园信息管理系统需求文档.docx")) { template.process(data, writer); } } } ``` ### 测试设计 ```java // 使用JUnit5测试实体类校验规则 class StudentValidationTest { @Test void whenScoreLessThan0_thenThrowException() { Student student = new Student(); assertThrows(IllegalArgumentException.class, () -> student.setScore(-5)); } @ParameterizedTest @CsvSource({"20230001, true", "20230002, false"}) void testCheckStudentNumberUnique(String number, boolean expected) { when(repository.existsByNumber(number)).thenReturn(expected); boolean result = service.checkNumberUnique(number); assertEquals(expected, result); } } ``` ### 相关问题 §§相关问题§§ 1. 如何优化RBAC权限管理的数据库设计? 2. Spring Boot中如何实现实体类的级联操作? 3. 系统如何保证高并发场景下的数据一致性? </think>### 校园信息管理系统需求分析文档(Java实现)分类方案 根据引用文档和系统特性,我将实现方案分为以下三类: --- ### 一、核心功能实现类(CRUD与业务逻辑) #### 1. 实体类设计(继承体系) ```java // 基类Person(抽象封装) public abstract class Person { private String id; // 学号/工号 private String name; private int age; // 封装校验规则 public void setAge(int age) { if(age <= 0) throw new IllegalArgumentException("年龄必须为正整数"); this.age = age; } // 公共getter/setter... } // 学生子类 public class Student extends Person { private String className; // 班级 private double score; // 成绩 public void setScore(double score) { if(score < 0 || score > 100) throw new IllegalArgumentException("成绩范围0-100"); this.score = score; } } // 教师子类 public class Teacher extends Person { private String subject; // 科目 private BigDecimal salary; // 薪资 public void setSalary(BigDecimal salary) { if(salary.compareTo(BigDecimal.ZERO) <= 0) throw new IllegalArgumentException("薪资必须为正数"); this.salary = salary; } } ``` #### 2. CRUD服务层实现 ```java // 学生服务接口 public interface StudentService { Student addStudent(Student student) throws DuplicateKeyException; Student getStudentById(String id); Student updateStudent(Student student) throws NotFoundException; void deleteStudent(String id); List<Student> searchStudents(String keyword); } // 服务实现(Spring Boot示例) @Service public class StudentServiceImpl implements StudentService { @Autowired private StudentRepository repository; @Override @Transactional public Student addStudent(Student student) { if(repository.existsById(student.getId())) { throw new DuplicateKeyException("学号已存在"); } return repository.save(student); } } ``` --- ### 二、系统架构类(技术实现框架) #### 1. Spring Boot主配置 ```java @SpringBootApplication public class CampusInfoSystemApp { public static void main(String[] args) { SpringApplication.run(CampusInfoSystemApp.class, args); } } ``` #### 2. 数据库集成(MyBatis + MySQL) ```xml <!-- pom.xml 依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> </dependency> ``` #### 3. RESTful接口设计 ```java @RestController @RequestMapping("/api/students") public class StudentController { @PostMapping public ResponseEntity<?> createStudent(@Valid @RequestBody Student student) { return ResponseEntity.created(URI.create("/students/" + student.getId())) .body(studentService.addStudent(student)); } } ``` --- ### 三、安全与扩展类(RBAC+校验) #### 1. RBAC权限控制 ```java // Spring Security配置 @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(auth -> auth .requestMatchers("/admin/**").hasRole("ADMIN") .requestMatchers("/teacher/**").hasAnyRole("TEACHER", "ADMIN") .requestMatchers("/student/**").hasAnyRole("STUDENT", "ADMIN") ); return http.build(); } } ``` #### 2. 数据校验增强 ```java // 自定义学号校验器 public class StudentIdValidator implements ConstraintValidator<ValidStudentId, String> { @Override public boolean isValid(String id, ConstraintValidatorContext context) { return id != null && id.matches("2024\\d{4}"); // 2024+4位数字 } } ``` #### 3. 扩展接口设计 ```java // 可扩展的模块接口 public interface InfoManageable<T> { T create(T entity); T update(T entity); void delete(String id); T getById(String id); } // 实现示例 @Service public class TeacherService implements InfoManageable<Teacher> { // 实现CRUD方法... } ``` --- ### 文档生成辅助工具 ```java // 自动生成需求文档(Freemarker示例) public class DocumentGenerator { public void generateDoc(Map<String, Object> data) { Configuration cfg = new Configuration(Configuration.VERSION_2_3_31); cfg.setClassForTemplateLoading(this.getClass(), "/templates"); Template template = cfg.getTemplate("requirement_template.ftl"); try(Writer writer = new FileWriter("需求文档.docx")) { template.process(data, writer); } } } ``` ### 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值