JdbcTemplate的关联查询与批量添加

本文介绍了在Windows10环境下,使用IDEA和JDK 1.8,基于Maven和JdbcTemplate进行数据库操作。重点讨论了如何处理关联查询,通过自定义RowMapper接口提高代码复用性,以及详细展示了批量添加数据的过程,包括处理表间关联关系,编写SQL语句,并通过batchUpdate方法实现批量插入。

一、开发环境

系统:windows10
开发工具:IDEA
jdk:1.8
框架:Maven

二、关联查询

若涉及到多个字段的查询,JdbcTemplate的查询方法query(sql,class)里的class只能是String.class或Integer.class,实用性不高,必须使用匿名内部类自定义一个返回的对象。否则会抛出异常:
Incorrect column count: expected 1, actual X

虽然可以在Dao类对象的查询方法中使用匿名内部类,但是查询方法过多每个方法都使用匿名内部类代码量巨大。

好的方法是在entity类中实现org.springframework.jdbc.core.RowMapper接口。
举个例子:

public class Student implements org.springframework.jdbc.core.RowMapper,Serializable {
    private int sid;//学号
    private String sname;//姓名
    private Classes classes;//所属班级
    private String sex;//性别
    private String birthplace;//出生地

    //。。。此处省略getset方法与构造函数

    //重写mapRow方法,替代之前的在每个方法中定义匿名内部类
    @Override
    public Student mapRow(ResultSet resultSet, int rowNum) throws SQLException {
        Student student = new Student();
        student.setSid(resultSet.getInt("sid"));
        student.setSname(resultSet.getString("sname"));
        student.setClasses(new Classes(resultSet.getInt("cid"),resultSet.getString("classname")));
        student.setSex(resultSet.getString("sex"));
        student.setBirthplace(resultSet.getString("birthplace"));
        return student;
    }

在Dao类中的方法:

    //查询所有的学生
    public List<Student> findAll() {
        List<Student> studentList = getJdbcTemplate().query(
            "select student.*,classes.classname from student,classes WHERE student.cid = classes.cid",
            new Student());
        return studentList;
    }

之前的写法是:

    //查找所有用户
    public List<User> findAll() {
        String sql = "select * from users";
        List<User> list = getJdbcTemplate().query(sql,
            rs -> {
                List<User> list1 = new ArrayList<>();
                while (rs.next())
                    list1.add(new User(rs.getInt("uid"), rs.getString("uname"), rs.getString("telephone"),
                        rs.getString("job"), rs.getString("address"), rs.getString("nationality")));
                return list1;
            }
        );
        return list;
    }

虽然使用了Lambda表达式,但是代码量也还是很多。
可见通过实体类实现RowMapper接口让关联查询的开发方便了许多。

三、批量添加

首先,我的数据库是这样的,学生表student中的cid是classes班级表的主键cid,之间具有表的关联性,因此在添加的过程中就应该思考需要添加的数据和流程有哪些。

这是student表和classes表的sql语句

CREATE TABLE classes
(
    cid int PRIMARY KEY auto_increment,
    cname varchar(20) not null
)

CREATE TABLE student
(
    sid int PRIMARY KEY auto_increment,
    sname VARCHAR(20) not NULL,
    cid int,
    sex VARCHAR(10) not null,
    birthplace VARCHAR(20) not null
)

--外键关联
alter table student add foreign key (cid) references classes (cid)

批量添加的sql语句应是:
insert into TABLE() values(),(),(),()
这样在values后面用括号进行多个数据批量插入添加。
可以使用batchUpdate()的方法进行批量添加

    //添加学生
    public void addStudent(List<Student> list) {
        final List<Student> studentList = list;
        String sql = "insert into student(sname,cid,sex,birthplace)"+"values(?,?,?,?)";
        this.getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
                preparedStatement.setString(1,studentList.get(i).getSname());
                preparedStatement.setInt(2,studentList.get(i).getClasses().getCid());
                preparedStatement.setString(3,studentList.get(i).getSex());
                preparedStatement.setString(4,studentList.get(i).getBirthplace());
            }

            @Override
            public int getBatchSize() {
                return studentList.size();
            }
        });
    }

我在Dao类还写了个根据classname(班级名)去获取到cid的方法,因此添加到student表还需要一个cid的字段,但是前端传过来的往往是班级名。

    //根据classname查找cids
    public Integer findClassBycname(String classname) {
        try {
            String sql = "SELECT cid from classes where classname like ?";
            return getJdbcTemplate().queryForInt(sql, new Object[]{classname});
        } catch (Exception e) {
            return null;
        }
    }

可是MVC的设计模式要求数据库操作与业务层分离,因此得通过Service层进行事务的处理:

    //该注解用于提交事务
    @Transactional(propagation = Propagation.REQUIRED)
    public void addStudent(List<Student> studentList, String classname) {
        Integer cid = studentDao.findClassBycname(classname);
        if (cid == null)
            return;
        else {
            for (Student stu : studentList) {
                stu.getClasses().setCid(cid);
            }
            studentDao.addStudent(studentList);
        }
    }

Test测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@Transactional
public class javaTest {

    @Autowired
    StudentServiceImpl studentService;

    @Test
    public void testService() {
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(1, "小云", new Classes(), "女", "昆明"));
        studentList.add(new Student(1, "小虹", new Classes(), "女", "重庆"));
        studentList.add(new Student(1, "小刚", new Classes(), "男", "遵义"));
        studentList.add(new Student(1, "小陈", new Classes(), "男", "贵阳"));
        studentService.addStudent(studentList,"财政1691");
        List list = studentService.findAll();

        for (Object stu : list) {
            System.out.println(stu);
        }
    }
}

输出结果:
输出结果

这两个算是之前增删查改实例扩展。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值