Spring JdbcTemplate框架(二)——动态建表

  本篇博客使用Spring JdbcTemplate实现动态建表。前面介绍了,它封装了数据库的基本操作,让我们使用起来更加灵活,下面来实战。

 

1、准备工作


引入jar



2applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

	<!-- JDBC 操作模板 --> 
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<constructor-arg>
			<ref bean="dataSource"/>
		</constructor-arg>
	</bean>		
 <!-- 配置数据库连接 -->
     <bean id="dataSource"  
         class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
         <property name="url" value="jdbc:mysql://localhost:3306/dynamic" />  
        <property name="username" value="root" />  
         <property name="password" value="123456" />  
     </bean>   
</beans>

3、代码


private static ApplicationContext context = null;
	//通过测试类测试
    public static void main(String[] args) {  
        context = new ClassPathXmlApplicationContext("applicationContext.xml");       
        Users user = new Users();  
        user.setUserName("liutengteng");  
        user.setUserPass("liutengteng");         
        int re = insertObject("users",user);  
        System.out.println("================" + re + "====================");  
    } 
    /**
     * 创建表,添加记录
     * @param tableName
     * @param obj
     * @return
     */
    public static int insertObject(String tableName,Object obj){  
        int re = 0;       
        try {  
            JdbcTemplate jt = (JdbcTemplate)context.getBean("jdbcTemplate");  
            SimpleDateFormat format = new SimpleDateFormat("yyyy_MM");            
            String tname = tableName + "_" + format.format(new Date());  
            // 判断数据库是否已经存在这个名称的表,如果有某表  则保存数据;否则动态创建表之后再保存数据
            if(getAllTableName(jt,tname)){  
                re = saveObj(jt,tname,obj);  
            }else{  
                re = createTable(jt,tname,obj);  
                re = saveObj(jt,tname,obj);  
            }             
        } catch (Exception e) {  
            e.printStackTrace();  
        }         
        return re;  
    } 
    /** 
     * 根据表名称创建一张表 
     * @param tableName 
     */  
    public static int createTable(JdbcTemplate jt,String tableName,Object obj){  
        StringBuffer sb = new StringBuffer("");  
        sb.append("CREATE TABLE `" + tableName + "` (");  
        sb.append(" `id` int(11) NOT NULL AUTO_INCREMENT,");          
        Map<String,String> map = ObjectUtil.getProperty(obj);  
        Set<String> set = map.keySet();  
        for(String key : set){  
            sb.append("`" + key + "` varchar(255) DEFAULT '',");  
        }         
        sb.append(" `tableName` varchar(255) DEFAULT '',");  
        sb.append(" PRIMARY KEY (`id`)");  
        sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");  
        try {  
            jt.update(sb.toString());  
            return 1;  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return 0;  
    }     
    
    /** 
     * 拼接语句,往表里面插入数据
     */  
    public static int saveObj(JdbcTemplate jt,String tableName,Object obj){  
        int re = 0;  
        try{              
            String sql = " insert into " + tableName + " (";  
            Map<String,String> map = ObjectUtil.getProperty(obj);  
            Set<String> set = map.keySet();  
            for(String key : set){  
                sql += (key + ",");  
            }  
            sql += " tableName ) ";               
            sql += " values ( ";  
            for(String key : set){  
                sql += ("'" + map.get(key) + "',");  
            }  
            sql += ("'" + tableName + "' ) ");  
            re = jt.update(sql);          
        } catch (Exception e) {  
            e.printStackTrace();  
        }         
        return re;  
    }     
    
   
    /** 
     * 查询数据库是否有某表 
     * @param cnn 
     * @param tableName 
     * @return 
     * @throws Exception 
     */  
    @SuppressWarnings("unchecked")  
    public static boolean getAllTableName(JdbcTemplate jt,String tableName) throws Exception {  
        Connection conn = jt.getDataSource().getConnection();  
        ResultSet tabs = null;  
        try {  
            DatabaseMetaData dbMetaData = conn.getMetaData();  
            String[]   types   =   { "TABLE" };  
            tabs = dbMetaData.getTables(null, null, tableName, types);  
            if (tabs.next()) {  
                return true;  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }finally{  
            tabs.close();  
            conn.close();  
        }  
        return false;  
    }

4、总结


          通过这种方式,让我们更加灵活的运用,但是也有弊端,如果系统的代码量很大,用最基本的这套框架就会有很多重复性的代码,这时就需要一层层的抽象,封装。抽象之后让代码的复用性更高。其实每一套框架也是抽象封装来的,不断的抽象封装,让我们的代码更灵活,质量更高。


  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Spring 出品的 JdbcTemplate 对于不想使用hibernate或者ibatis那样需要大量学习成本而且还想获得对象化的人来说是很好用的。但是 JdbcTemplate还是有很多不足之处或者说是缺点。比如你没法像hibernate那样直接传一个对象给它让他拆分成sql并保存起来,当然这也是可以理解的,毕竟它并没有要求你去写 hbm.xml 文件所以无法知道你哪些字段要映射,哪些不要等等。又比如JdbcTemplate 可以帮忙把一个查询结果传化为一个对象列表,但是你需要查阅一些资料才知道要用 BeanPropertyRowMapper 。如果下次要用的时候又忘记了这个类,又要查一次或者翻以前的代码来看,其实完全可以提供一个方法直接传一个PO类进去自动创建BeanPropertyRowMapper 。基于以上的一些不足之处,我建立了 JdbcTemplateTool 它有以下特性:把查询结果转换为PO列表,不需要调用BeanPropertyRowMapper传一条统计sql比如 aselect count(1) from table可以直接返回一个数字作为结果,不需要自己实现中间步骤。可以直接把一个PO类存到数据库通过PO类和一个id可以获取到该对象通过PO类可以直接update数据库记录不需要实现 BatchPreparedStatementSetter, 就可以批量update通过一个对PO对象删除对应的数据库记录依然可以使用原始的JdbcTemplate目前只在mysql上测试.Maven 依赖<dependency>   <groupId>org.crazycake</groupId>   <artifactId>jdbctemplatetool</artifactId>   <version>1.0.4-RELEASE</version> </dependency>快速开始STEP 1. 创建一个maven项目    创建一个maven项目叫testjtt. 添加jdbctemplatetool 依赖到pom.xml. 再添加以下依赖到 pom.xml.<dependency>   <groupId>junit</groupId>   <artifactId>junit</artifactId>   <version>4.11</version>   <scope>test</scope> </dependency> <dependency>     <groupId>org.springframework</groupId>     <artifactId>spring-context</artifactId>     <version>3.2.2.RELEASE</version>     <scope>test</scope> </dependency> <dependency>     <groupId>com.mchange</groupId>     <artifactId>c3p0</artifactId>     <version>0.9.2.1</version>     <scope>test</scope> </dependency> <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>5.1.19</version>     <scope>test</scope> </dependency> <dependency>     <groupId>org.springframework</groupId>     <artifactId>spring-test</artifactId>     <version>3.2.2.RELEASE</version>     <scope>test</scope> </dependency>最好使用 1.6 jdk. 我并没有在 1.5 下测试STEP 2. 创建测试数据库    创建一个测试的数据库叫jtt_test创建一个用户travis不要分配密码. 赋予jtt_test的权限给travis.CREATE USER 'travis'@'%' IDENTIFIED BY ''; GRANT ALL ON jtt_test.* TO 'travis'@'%'; flush privileges;创建一张表employee插入一些测试数据.DROP TABLE IF EXISTS `employee`; CREATE TABLE `employee` (   `id` int(11) NOT NULL,   `name` varchar(300) NOT NULL,   `join_date` datetime NOT NULL,   `age` int(11) NOT NULL,   PRIMARY KEY  (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `employee` */ insert  into `employee`(`id`,`name`,`join_date`,`age`) values (1,'jack','2014-09-22 00:00:00',23),(2,'ted','2014-08-30 00:00:00',25),(3,'jim','2014-06-22 00:00:00',33);STEP 3. 配置一下spring    在test文件夹下创建resources文件夹. 添加resources到 source folder 修改输出为target/test-classes创建spring.xml在 test/resources 里面<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">     <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">         <property name="jdbcUrl"><value>jdbc:mysql://localhost:3306/jtt_test?characterEncoding=utf8</value></property>         <property name="driverClass"><value>com.mysql.jdbc.Driver</value></property>         <property name="user"><value>travis</value></property>         <property name="password"><value></value></property>     </bean>     <bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">             <property name = "dataSource" ref="dataSource"/>        </bean>     <bean id="jdbcTemplateTool" class="org.crazycake.jdbcTemplateTool.JdbcTemplateTool">         <property name = "jdbcTemplate" ref="jdbcTemplate" />     </bean> </beans>STEP 4. 创建PO类    创建Employee.javaimport java.sql.Timestamp; import javax.persistence.Id; public class Employee {     private Integer id;     private String name;     private Timestamp joinDate;     private Integer age;     @Id     public Integer getId() {         return id;     }     public void setId(Integer id) {         this.id = id;     }     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public Timestamp getJoinDate() {         return joinDate;     }     public void setJoinDate(Timestamp joinDate) {         this.joinDate = joinDate;     }     public Integer getAge() {         return age;     }     public void setAge(Integer age) {         this.age = age;     } }STEP 5. 创建测试用例    创建HelloJTTTest.javaimport static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import java.util.List; import org.crazycake.jdbcTemplateTool.JdbcTemplateTool; import org.junit.Test; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; @ContextConfiguration(locations={"classpath:spring.xml"}) public class HelloJTTTest extends AbstractJUnit4SpringContextTests{     @Test     public void testSave(){         JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);         Employee e = new Employee();         e.setId(4);         e.setName("billy");         Date now = new Date();         e.setJoinDate(new Timestamp(now.getTime()));         e.setAge(33);         try {             jtt.save(e);         } catch (Exception e1) {             e1.printStackTrace();         }     } }STEP 6. 启动!    运行测试用例,等待绿色条。然后去数据库会看到多了一条记录 :idnamejoin_dateage4billy2014-09-24 22:51:2033高级教程    以下是各个方法的详细介绍list把查询结果转换为PO列表,不需要调用BeanPropertyRowMapper。 自动根据数据库的列将下划线转为驼峰命名规则映射类的属性.@Test public void testList(){     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     List<Employee> es = jtt.list("select * from employee where age < ? order by id desc", new Object[]{30}, Employee.class);     assertThat(new Integer(es.size()),is(2));     assertThat(es.get(1).getName(),is("jack")); }count    传一条统计sql比如 aselect count(1) from table可以直接返回一个数字作为结果,不需要自己实现中间步骤。@Test public void testCount() throws IOException, SQLException {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     int total = jtt.count("select count(1) from employee", null);     assertThat(total,is(4));     }save可以直接把一个PO类存到数据库。如果你不想把某个列映射为数据库字段可以使用 @Trasient 注解在getter上public class Student {     private Integer id;     private String name;     private String nothing;     public Integer getId() {         return id;     }     public void setId(Integer id) {         this.id = id;     }     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     @Transient     public String getNothing() {         return nothing;     }     public void setNothing(String nothing) {         this.nothing = nothing;     } }这个字段会被跳过@Test public void testSave() throws Exception {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     Student s = new Student();     s.setName("michael");     s.setNothing("nothing");     jtt.save(s); }get    通过PO类和一个id可以获取到该对象。但是前提是需要在主键的getter上标上 @Id 注解@Id public Integer getId() {     return id; }例子@Test public void testGet() throws NoIdAnnotationFoundException, NoColumnAnnotationFoundException, IOException, SQLException {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     Employee e = jtt.get(Employee.class, 3);     assertThat(e.getName(),is("jim")); }update    自动根据PO类更新数据库. 记得增加@Id.@Test public void testUpdate() throws Exception {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     Employee e = jtt.get(Employee.class, 1);     e.setAge(23);     jtt.update(e); }batchUpdate    批量更新@Test public void testBatchUpdate() throws SQLException, IOException {     build();     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     List<Object[]> params = new ArrayList<Object[]>();     Object[] p1 = new Object[]{23,"jack"};     params.add(p1);     Object[] p2 = new Object[]{29,"tim"};     params.add(p2);     jtt.batchUpdate("update employee set age = ? where name = ?", params); }delete    删除数据库对象@Test public void testDelete() throws Exception {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     Employee e = new Employee();     e.setId(1);     jtt.delete(e); }getJdbcTemplate    你依然可以使用原始的JdbcTemplate. 调用JdbcTemplateTool.getJdbcTemplate()to getJdbcTemplate就可以了。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值