选用的数据库是MySQL数据库,在数据库中创建一个student表。
建表语句如下:
create table student(
id int not null primary key auto_increment,
name varchar(20) not null,
age int not null
);
初始的时候在表中添加一些数据
insert into student(name,age)
values
("小李子",18),
("关小羽",15),
("盖伦",33);
现在,表和表中的数据已经有了,接下来就是代码的编写。
首先是spring的核心包4个,在这里程序中使用项目构建工具maven来管理依赖。
接下来是使用spring的jdbc包进行数据库的操作,以及test包为了整合Junit。当然,既然要用到junit,那么也必须添加进来。
最后是MySQL数据库的驱动。
至此,一共是8个jar包。但是,由于maven会在引入一个jar包的同时,帮助你导入一些相关的依赖,所以最后的数量会大于8个。
根据ORM思想,数据库中的一个表对应了Java的一个类,表中的一行记录对应了类的一个实例。这里创建了StudentDO类
/**
* 根据orm思想对应数据库中的student表
*/
public class StudentDO {
private int id;
private String name;
private int age;
public StudentDO() {
}
public StudentDO(String name, int age) {
this.name = name;
this.age = age;
}
public StudentDO(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "UserDO{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
这里提供了三个构造器,虽然只用到了两个,但是还是要说一下三个构造器的用途。空参构造器,是为了方便进行反射然后通过反射赋值;两个参数的构造器一般作为参数传入,因为student表的id字段是自增的,所以不需要额外设置;三个参数的构造器一般是作为查询方法的返回结果返回的。
Dao包下的类中的方法都是直接操作数据库的。根据面向接口的原则,先定义一个StudentDao接口,接口中包含了对student表操作的几个方法,方法要实现的功能见下面代码中方法前的注释。
public interface StudentDao {
/**
* 查询表中学生的数量
* @return
*/
int getStudentNumbers();
/**
* 根据id查询对应的学生
* @param id
* @return
*/
StudentDO queryStudentById(int id);
/**
* 返回所有的学生列表
* @return
*/
List getAllStudents();
/**
* 在表中增加一个学生记录
* @param student
*/
void addStudent(StudentDO student);
/**
* 在表中修改一条学生记录
* @param id
*/
void updateStudent(StudentDO student, int id);
/**
* 根据id删除学生记录
* @param id
*/
void deleteStudent(int id);
}
public class StudentDaoImpl implements StudentDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public int getStudentNumbers() {
String sql = "select count(*) from student";
Integer num = jdbcTemplate.queryForObject(sql, Integer.class);
return num;
}
@Override
public StudentDO queryStudentById(int id) {
String sql = "select * from student where id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper(StudentDO.class));
}
@Override
public List getAllStudents() {
String sql = "select * from student";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper(StudentDO.class));
}
@Override
public void addStudent(StudentDO student) {
String sql = "insert into student(name, age) values(?, ?)";
jdbcTemplate.update(sql, student.getName(), student.getAge());
}
@Override
public void updateStudent(StudentDO student, int id) {
String sql = "update student set name = ?, age = ? where id = ?";
jdbcTemplate.update(sql, student.getName(), student.getAge(), student.getId());
}
@Override
public void deleteStudent(int id) {
String sql = "delete from student where id = ?";
jdbcTemplate.update(sql, id);
}
}
这里有几点要说明一下。
使用jdbcTemplate,那么一定要设置连接池DataSource,这里连接池的选用使用的是spring-jdbc包里自带的DriverManagerDataSource。对于常用的三种连接池c3p0、dbcp、Druid,推荐使用Druid。c3p0稳定但是性能不好,dbcp稳定性不是很高,Druid综合了前两个的优点,并且可以进行sql优化和性能调优。
具体配置如下:
这里对于连接池的参数使用了一个properties文件,然后将properties文件放入spring容器中。
注意:这里读取properties文件的配置使用了context的命名空间,需要在xml的schema中添加context的命名空间。
// 下面两个注解自动加载配置文件并加载测试环境,再将类中属性自动注入
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:jdbc.xml")
public class JdbcTemplateTest {
@Autowired
private StudentDaoImpl studentDao;
@Test
public void testJdbcTemplate() {
int num = studentDao.getStudentNumbers();
System.out.println("当前有" + num + "个学生");
System.out.println("--------");
System.out.println("学生的详细信息");
List allStu = studentDao.getAllStudents();
allStu.forEach(System.out::println);
System.out.println("--------");
StudentDO studentDO = new StudentDO("大司马", 43);
studentDao.addStudent(studentDO);
StudentDO student = studentDao.queryStudentById(4);
System.out.println("新加的学生" + student);
System.out.println("-------");
student.setAge(17);
studentDao.updateStudent(student, 4);
student = studentDao.queryStudentById(4);
System.out.println("修改年龄后" + student);
studentDao.deleteStudent(4);
System.out.println("--------");
System.out.println("学生的详细信息");
allStu = studentDao.getAllStudents();
allStu.forEach(System.out::println);
}
}
测试结果:
结合Junit需要spring-test包,在测试类上添加@Runwith(SpringJunit4ClassRunner.class),这是表明该类进行测试的时候自动加载测试环境,@ContextConfiguration(locations=“classpath:xml的路径”),加载配置文件,对类中自动注入的属性进行注入。
注意:
1.Junit包要选择4.12以上的,否则运行会报错(而且报错信息提示你要使用Junit4.12或以上的版本)
2.locations属性的值要添加classpath,因为tomcat的路径和项目路径是不一样的,项目发布时会报找不到文件异常。另外,idea默认的classpath是target/classes目录下,所以要设置resources目录并标记为资源文件夹,这样才会在编译时将其放入classpath路径下。
最好,对于上面的程序,只是一个小demo,熟悉一下JdbcTemplate的使用。
实际上,StudentDaoImpl可以继承JdbcDaoSupport类,该类可以直接注入DataSource,在类中自动newJdbcTemplate实例,通过getJdbcTemplate()获得该实例。