第一步建表:
第二步:编写product表的实体类
public class produce { private int id; private String name; private String price; /** * @return the id */ public int getId() { return id; } /** * @param id the id to set */ public void setId(int id) { this.id = id; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the price */ public String getPrice() { return price; } /** * @param price the price to set */ public void setPrice(String price) { this.price = price; } }
第三步:编写productDao,完成基本的常见操作。
这立即有个问题,我们想要使用的是Spring的JdbcTemplate来操作数据库,那么我们应该在productDao类注入JdebcTemplate,我们想到的方式是定义一个成员变量,然后
注入,但是Spring 已经为我们考虑了这种情况,所以提供了一个JdbcDaoSupport类来帮助我们。这个类里面提供了setjdbcTempalte这样的方法。
/* * 我们要用Spring的JDBC模板(JdbcTemplate)第一想法是在这个类中 * 定义一个成员变量,然后用set方法,用Spring去注入。但是Spring已经为我们 * 考虑好了这个情况。我们不需要自己去写什么setJdbcTemplate这个方法,只要去 * 继承jdbcDaoSupport这个类就可以了。在这个类里面已经有了setJdbcTemplate这个方法。 * */ public class ProductDao extends JdbcDaoSupport { //增 public void save(produce produce1 ) { String sql="insert into product values(null,?,?)"; this.getJdbcTemplate().update(sql, produce1.getName(),produce1.getPrice()); } //改 public void update(produce produce1) { String sql="update product set name=?,price=? where id=?"; this.getJdbcTemplate().update(sql, produce1.getName(),produce1.getPrice(),produce1.getId()); }//删public void delete( produce produce1){String sql="delete from product where id=?";this.getJdbcTemplate().update(sql, produce1.getId()); } }
第四步:配置Spring的ApplicationContext.xml文件。
<!-- 引入peoperties文件 --> <!-- <context:property-placeholder location="classpath:db.properties"/> --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations" value="classpath:db.properties"/> </bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${driver}"/> <property name="jdbcUrl" value="${url}"></property> <property name="user" value="${username}"></property> <property name="password" value="${password}"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 给 ProductDao的父类里面的jdbcTemplate注入值--> <bean id="ProductDao" class="cn.itcast.spring.c_jdbc.ProductDao"> <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean>
第五步:编写Junit测试代码
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:applicationContext.xml") public class ProductTest { @Autowired private ProductDao productDao; //@Test public void testsave() { produce produce1=new produce(); produce1.setName("爱"); produce1.setPrice("100"); this.productDao.save(produce1); } //@Test public void testupdate() { produce produce2=new produce(); produce2.setId(1); produce2.setName("爱2"); produce2.setPrice("200"); this.productDao.update(produce2); } @Test public void testdelete() { produce produce1Produce=new produce(); produce1Produce.setId(2); this.productDao.delete(produce1Produce); } }
上面对增删改都讲解了,下面对查找单独拿出来讲解。查找分为两块讲解,简单的查找和复杂的查找。
简单的查找:
如果返回结果 是一个简单值,使用jdbcTemplate 提供 queryForXXX 方法
比如:queryForInt 返回结果是int
queryForLong 返回结果是long
queryForObject 返回结果是Object (返回String )
针对上面三种方法,分别写两个方法。
查找商品的数量和查找商品的名字
//查找商品的数量 public long findTotleCount() { String sql="select count(*) from produce"; return this.getJdbcTemplate().queryForLong(sql); } //查找商品的名称 public String findNamebyId(int id) { String sql="select name from product where id=?"; return this.getJdbcTemplate().queryForObject(sql, String.class, id); }
在Junit中编写相应的测试代码:
//测试查找商品的名称 //@Test public void testfindNameById() { String name=this.productDao.findNamebyId(1); System.out.print(name); } //测试查找商品的总数 @Test public void testTotleCount() { long count=this.productDao.findTotleCount(); System.out.print("aaaaaaa"+count); }
结果:输出都是对的。
题外话:
通用的多表查询其实有个致命的缺点。以马成老师的DataBaseClass类为例。这个类有一个致命的缺点,那就是在多表查询的时候,比如
select * from custom,order where custom.orderid=orider.id and custom.id=? 这里涉及到两张表,查询得到的字段有两张表的所有的字段。那么就有一个问题了。
我并没有针对两个表的字段的实体类啊,为了这个我还要重新创建对应的实体类,万一我以后的字段在少一个,那不是要经常改变了啊。这就是他的致命缺点。
但是Hibernate就很好的解决了这个问题。因为Hibernate中每个实体类都有相应的.hbm.xml所以查出来的结果都是保存在各自的实体类中的。
复杂查询放在最后讲:
复杂查询返回对象:
JdbcTemplate 并没有提供 像Apache DbUtils框架 那样Handler ,而是需要手动封装结果集(就是说我们要自己从数据库把一个一个数据拿出来,
自己再把它封装成一个对象。)
------------ 通常企业开发中, 开发人员会为每个表,编写单独结果集封装程序 (RowMapper)
所以我们要自己手动封装结果集(RowMapper)。注意用了RowMapper,我们只要关心一行数据的每一个值的封装,不要关心怎么换行。
rs.next()什么的,都不用我们关心。
第一步:先写一个内部类继承RowMapper<>
第二步:再写相应的查找结果的方法。
//第一步: private class ProductRowMapper implements RowMapper<produce> { public produce mapRow(ResultSet rs, int rowNum) throws SQLException { produce produce1=new produce(); produce1.setId(rs.getInt("id")); produce1.setName(rs.getString("name")); produce1.setPrice(rs.getString("price")); return produce1; } } //第二步:根据id把数据库中的其中一个product对象找出来持久化。 public produce findproduceById(int id) { String sql="select * from product where id=?"; return this.getJdbcTemplate().queryForObject(sql, new ProductRowMapper(),id); }
第三步:编写Junit测试代码:
@Test public void testfindProduct() { produce produce1=this.productDao.findproduceById(1); //测试得到的结果是不是对的 System.out.print(produce1.getId()+produce1.getName()+produce1.getPrice()); }
结果:对的。
这里最核心的就是RowMapper。