• Spring的JdbcTemplate使用教程


    Spring对数据库的操作在jdbc上面做了基本的封装,让开发者在操作数据库时只需关注SQL语句和查询
    结果处理器,即可完成功能(当然,只使用JdbcTemplate,还不能摆脱持久层实现类的编写)。
    在配合spring的IoC功能,可以把DataSource注册到JdbcTemplate之中。同时利用spring基于
    aop的事务即可完成简单的数据库CRUD操作。
    JdbcTemplate的限定命名为org.springframework.jdbc.core.JdbcTemplate。要使用
    JdbcTemlate需要导入spring-jdbc和spring-tx两个坐标。

    方法说明:

    execute方法:
    可以用于执行任何SQL语句,一般用于执行DDL语句;
    update方法及batchUpdate方法:
    update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语
    句;
    query方法及queryForXXX方法:
    用于执行查询相关语句;
    call方法:
    用于执行存储过程、函数相关语句。


    使用案例

    项目结构:


    项目代码

    POM.XML

        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.1.6.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>5.1.6.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.45</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.1.6.RELEASE</version>
            </dependency>
    
        </dependencies>
    

    实体类:

    public class Account implements Serializable {
    
        private Integer id;
        private String name;
        private Double money;
        //省略getter setter
    }
    
    public class Userinfo implements Serializable {
    
        private Integer id;
        private byte[] images; // 对应mysql数据库longBlob类型
        private String description;  // 对应表的longText类型
    	// 省略getter setter
    }
    

    相对应account表和userinfo表


    jdbc.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/spring_ioc
    jdbc.username=root
    jdbc.password=admin
    

    jbbc配置类:

    public class JdbcConfig {
    
        @Value("${jdbc.driver}")
        private String driver;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
    
        /**
         * 创建数据源并存入Ioc容器
         * @return
         */
        @Bean
        public DataSource createDataSource(){
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName(driver);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            return dataSource;
        }
    
        /**
         * 创建JdbcTemplate对象
         * @param dataSource
         * @return
         */
        @Bean
        public JdbcTemplate createJdbcTemplate(DataSource dataSource){
            return new JdbcTemplate(dataSource);
        }
    	
        // 操作clob和blob
        @Bean
        public LobHandler createLobHandler(){
            return new DefaultLobHandler();
        }
    
    
    }
    

    主配置类:

    @Configuration
    @Import(JdbcConfig.class)
    @PropertySource("classpath:jdbc.properties")
    public class SpringConfiguration {
    }
    
    

    测试类:

    /**
    	*注释部分为不同写法
     * 测试JdbcTemplate的使用
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfiguration.class)
    public class SpringJdbcTemplateTest {
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Test
        public void testSave(){
            jdbcTemplate.update("insert into account(money,name)values(?,?)",6789d,"userTest");
        }
    
        @Test
        public void testUpdate(){
            jdbcTemplate.update("update account set name=?,money=? where id=?","testZZZ",23456d,3);
        }
    
        @Test
        public void testDelete(){
            jdbcTemplate.update("delete from account where id = ? ",4);
        }
    
        @Test
        public void testFindOne(){
    //        List<Account> accounts =  jdbcTemplate.query("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),1);
    //        System.out.println(accounts.isEmpty()?"empty":accounts.get(0));
    
    //        Account account = jdbcTemplate.queryForObject("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),1);
    //        System.out.println(account);
    
            Account account = jdbcTemplate.query("select * from account where id = ?", new ResultSetExtractor<Account>() {
                @Override
                public Account extractData(ResultSet rs) throws SQLException, DataAccessException {
                    Account account1 = null;
                    //1.判断结果集能往下走
                    if(rs.next()){
                        account1 = new Account();
                        account1.setId(rs.getInt("id"));
                        account1.setName(rs.getString("name"));
                        account1.setMoney(rs.getDouble("money"));
                    }
                    return account1;
            }
            }, 1);
            System.out.println(account);
        }
    
        @Test
        public void testFindAll(){
            List<Account> accountList = jdbcTemplate.query("select * from account where money > ?",new BeanPropertyRowMapper<Account>(Account.class),999d);
            for(Account account : accountList){
                System.out.println(account);
            }
        }
    
        @Test
        public void testFindCount(){
           Integer count =  jdbcTemplate.queryForObject("select count(*) from account where money > ?",Integer.class,999d);
            System.out.println(count);
        }
    
    
        @Test
        public void testQueryForList(){
            /**
             * 得到某个特定类型的集合。类型是方法的第二个参数指定的
             */
            List<Double> list = jdbcTemplate.queryForList("select money from account where money > ?",Double.class,999d);
            for(Double money : list){
                System.out.println(money);
            }
    
    //        List<Map<String,Object>> list = jdbcTemplate.queryForList("select * from account where money > ? ",999d);
    //        for(Map<String,Object> map : list){
    //            for(Map.Entry<String,Object> me : map.entrySet())
    //            System.out.println(me.getKey()+","+me.getValue());
    //        }
        }
    
        @Test
        public void testQueryForMap(){
            Map<String,Object> map = jdbcTemplate.queryForMap("select * from account where id = ?",1);
            for(Map.Entry<String,Object> me : map.entrySet()) {
                System.out.println(me.getKey()+","+me.getValue());
            }
        }
    
    
        @Test
        public void testQueryForRowSet(){
            SqlRowSet rowSet = jdbcTemplate.queryForRowSet("select * from account where money > ?",999d);
            System.out.println(rowSet);
            while(rowSet.next()){
                String name = rowSet.getString("name");
                System.out.println(name);
            }
        }
    }
    
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfiguration.class)
    public class SpringLobTest {
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Autowired
        private LobHandler lobHandler;
    
        @Test
        public void testWrite(){
            try {
                //准备images的字节数组
                Resource resource = new FileSystemResource("E:\6.jpg");
                byte[] images = FileCopyUtils.copyToByteArray(resource.getFile());
                //准备description
                String description = "BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器。
    " +
                        "在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型。
    " +
                        "BLOB是一个大文件,典型的BLOB是一张图片或一个声音文件,
    " +
                        "由于它们的尺寸,必须使用特殊的方式来处理(例如:上传、下载或者存放到一个数据库)。
    " +
                        "根据Eric Raymond的说法,处理BLOB的主要思想就是让文件处理器(如数据库管理器)不去理会文件是什么,
    " +
                        "而是关心如何去处理它。但也有专家强调,这种处理大数据对象的方法是把双刃剑,
    " +
                        "它有可能引发一些问题,如存储的二进制文件过大,会使数据库的性能下降。
    " +
                        "在数据库中存放体积较大的多媒体对象就是应用程序处理BLOB的典型例子。";
                //1.创建Userinfo
                Userinfo userinfo = new Userinfo();
                userinfo.setImages(images);
                userinfo.setDescription(description);
    
                jdbcTemplate.execute("insert into userinfo(images,description)values(?,?)", new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
                    @Override
                    protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, DataAccessException {
                        lobCreator.setBlobAsBytes(ps, 1, userinfo.getImages());
                        lobCreator.setClobAsString(ps, 2, userinfo.getDescription());
                    }
                });
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        @Test
        public void testRead(){
    //        Userinfo userinfo = jdbcTemplate.queryForObject("select * from userinfo where id = ?",new BeanPropertyRowMapper<Userinfo>(Userinfo.class),1);
            Userinfo userinfo = jdbcTemplate.query("select * from userinfo where id = ?", new ResultSetExtractor<Userinfo>() {
                @Override
                public Userinfo extractData(ResultSet rs) throws SQLException, DataAccessException {
                    Userinfo userinfo1 = null;
                    if(rs.next()){
                        userinfo1 = new Userinfo();
                        userinfo1.setId(rs.getInt("id"));
                        userinfo1.setImages(lobHandler.getBlobAsBytes(rs,"images"));
                        userinfo1.setDescription(lobHandler.getClobAsString(rs,"description"));
                    }
                    return userinfo1;
                }
            }, 1);
            System.out.println(userinfo);
        }
    }
    
    

    具名参数使用

    在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制. 定位参数的问题在于,一旦参数的顺序发生变化, 就必须改变参数绑定.在 Spring JDBC 框架中, 绑定 SQL 参数的另一种选择是使用具名参数(namedparameter).那么什么是具名参数?具名参数: SQL 按名称(以冒号开头)而不是按位置进行指定. 具名参数更易于维护, 也提升了可读性. 具名参数由框架类在运行时用占位符取代具名参数只NamedParameterJdbcTemplate 中得到支持。NamedParameterJdbcTemplate可以使用全部jdbcTemplate方法。

    在jdbcConfig中加入组件

        @Bean
        public NamedParameterJdbcTemplate createNamedParameterJdbcTemplate(JdbcTemplate jdbcTemplate){
            return new NamedParameterJdbcTemplate(jdbcTemplate);
        }
    

    测试类:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfiguration.class)
    public class SpringNamedParameterJdbcTemplateTest {
    
        @Autowired
        private NamedParameterJdbcTemplate jdbcTemplate;
    
        @Test
        public void testFind(){
            Map<String,Object> map = new HashMap<>();
            map.put("id",1);
            Account account = jdbcTemplate.queryForObject("select * from account where id = :id",map,new BeanPropertyRowMapper<Account>(Account.class));
            System.out.println(account);
        }
    
    
        @Test
        public void testSave(){
            Account account = new Account();
            account.setName("NamedParameterJdbcTemplate");
            account.setMoney(12345d);
            BeanMap beanMap = BeanMap.create(account);
            jdbcTemplate.update("insert into account(name,money)values(:name,:money)",beanMap);
        }
    }
    
  • 相关阅读:
    详解java定时任务
    Java之Exception
    Java设计模式
    Java中的static关键字解析
    浅析Java中的final关键字
    深入理解Java的接口和抽象类
    一个故事讲清楚NIO
    Java并发编程:线程池的使用
    Java垃圾回收机制
    ubuntu sublime text 2 破解版
  • 原文地址:https://www.cnblogs.com/heliusKing/p/11877314.html
Copyright © 2020-2023  润新知