1.看图
2.实体类:
package com.domin; import java.io.Serializable; public class Account implements Serializable { private Integer id; private String name; private Float money; 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 Float getMoney() { return money; } public void setMoney(Float money) { this.money = money; } @Override public String toString() { return "Account{" + "id=" + id + ", name='" + name + '\'' + ", money=" + money + '}'; } }
//(重写toString)
3.业务层接口:IAccountService
package com.service; import com.domin.Account; import java.util.List; public interface IAccountService { /*查询所有*/ List<Account> findAllAccount(); /*查询一个*/ Account findAccountById(Integer accountId); /*保存一个*/ void saveAccount(Account account); /*更新*/ void updateAccount(Account account); /*删除一个*/ void deleteAccount(Integer accountId); }
4.业务层实现类(写入方法)AccountServiceImp:
package com.service.Imp; import com.dao.IAccountDao; import com.domin.Account; import com.service.IAccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /*交给spring容器去管理*/ @Service("accountService") public class AccountServiceImp implements IAccountService { /*交给spring容器去管理:配置accountService中的accountDao*/ @Autowired //调用持久层 private IAccountDao accountDao; /*当使用注解的时候,set方法就不是必须的了*/ /*public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; }*/ @Override public List<Account> findAllAccount() { return accountDao.findAllAccount(); } @Override public Account findAccountById(Integer accountId) { return accountDao.findAccountById(accountId); } @Override public void saveAccount(Account account) { accountDao.saveAccount(account); } @Override public void updateAccount(Account account) { accountDao.updateAccount(account); } @Override public void deleteAccount(Integer accountId) { deleteAccount(accountId); } }
5.持久层接口IAccountDao:
package com.dao; import com.domin.Account; import java.util.List; public interface IAccountDao { /*查询所有*/ List<Account> findAllAccount(); /*查询一个*/ Account findAccountById(Integer accountId); /*保存一个*/ void saveAccount(Account account); /*更新*/ void updateAccount(Account account); /*删除一个*/ void deleteAccount(Integer accountId); }
6.持久层实现类:AccountDaoImp
package com.dao.Imp; import com.dao.IAccountDao; import com.domin.Account; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import java.util.List; /*交给spring去管理*/ @Repository("accountDao") public class AccountDaoImp implements IAccountDao { @Autowired/*不指定的话默认类名为id*/ private QueryRunner runner;/*自动注入它的方法:当使用注解的时候set的方法既不是必须的了*/ /*public void setRunner(QueryRunner runner) { this.runner = runner; }*/ @Override public List<Account> findAllAccount() { /*泛型使用字解码创建对象*/ try{ return runner.query("select * from account",new BeanListHandler<Account>(Account.class)); }catch (Exception e){ throw new RuntimeException(e); } } @Override public Account findAccountById(Integer accountId) { try{ return runner.query("select * from account where id = ?",new BeanHandler<Account>(Account.class),accountId); }catch (Exception e){ throw new RuntimeException(e); } } @Override public void saveAccount(Account account) { try{ runner.update("insert into account(name,money)value(?,?)",account.getName(),account.getMoney()); }catch (Exception e){ throw new RuntimeException(e); } } @Override public void updateAccount(Account account) { try{ runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId()); }catch (Exception e){ throw new RuntimeException(e); } } @Override public void deleteAccount(Integer accountId) { try{ runner.update("delete from account where id=?",accountId); }catch (Exception e){ throw new RuntimeException(e); } } }
7.配置类(大模块)ConfigurationTest
package config; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.apache.commons.dbutils.QueryRunner; import org.springframework.context.annotation.*; import javax.sql.DataSource; /* * 该类是一个配置类,它的作用和bean.xml是一样的 * spring中的新注解 * Configuration * 作用:指定当前类是一个配置类 * 细节: * 当配置类作为AnnotationConfigApplicationContext对象创建的参数的时候,该注解可以不写。 * (在测试类当中,直接通过类名.class传入,然后注解直接被扫描解读、、但是不绝对) * 为什么:当你独立开始使用jdbcConfig的时候,那么AnnotationConfigApplicationContext里面的配置文件 * 不再进行整个包的扫描,而是只单独解析类,所以,我们的@Configuration得注上,预防隔离开来的单独一个文件, * 所以进行扫描包的注解还是必须的 * * ComponentScan * 作用:用于通过注解指定spring在创建容器时要扫描的包。 * 属性: * value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。 * 我们使用此注解就等同于在XML中配置了:扫描包的语法 * <context:component-scan base-package="com"></context:component-scan> * Bean * 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中 * (容器是有键值对的[key,value],不写有默认值) * 属性: * name:用于指定bean的id。默认值是当前方法的名称 * 细节:当我们使用注解配置方法的时候,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象 * 查找的方式和Autowired是一样的 * Scope:作用域(单例singleton、多例prototype) * Import * 作用:用于导入其他的配置类 统一在大模块中导入,然后分别写小的子类模块就可以 * 属性: * value:用于指定其他配置类的字节码。 * 当我们使用Import的注解之后,有Import注解的类就是父配置类,而导入的都是子配置类 * */ /*替代xml中的配置文件*/ @Configuration //@ComponentScan({"com","config"}) 这里多个必须使用对象 @ComponentScan("com") @Import(JdbcConfig.class)/*引入*/ public class ConfigurationTest { /* * 用于创建一个 QueryRunner对象 * * */ /*全部移入到JdbcConfig中去*/ // @Bean(name="runner")/*用于把当前方法的返回值作为bean对象存入spring的ioc容器中*/ // @Scope("prototype")/*默认单例,变为多例*/ // public QueryRunner createQueryRunner(DataSource dataSource){ // return new QueryRunner (dataSource); // } // /* // * 创建数据源对象 // * // * */ // /*和上面的dataSource一样:这样容器中就有了这个对象,就不会报错*/ // @Bean(name = "dataSource") // public DataSource createDataSource(){ // try { // ComboPooledDataSource dataSource = new ComboPooledDataSource(); // dataSource.setDriverClass("com.mysql.jdbc.Driver"); // dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/eesy"); // dataSource.setUser("root"); // dataSource.setPassword("123456"); // return dataSource; // }catch (Exception e){ // throw new RuntimeException(e); // } // } }
8.配置类子模块:JdbcConfig
package config; /* * 使用Junit单元测试,测试我们的配置 * * */ import com.mchange.v2.c3p0.ComboPooledDataSource; import org.apache.commons.dbutils.QueryRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import javax.sql.DataSource; //@Configuration 已经在大模块使用@Import了 public class JdbcConfig { @Bean(name="runner")/*用于把当前方法的返回值作为bean对象存入spring的ioc容器中*/ @Scope("prototype")/*默认单例,变为多例*/ public QueryRunner createQueryRunner(DataSource dataSource){ return new QueryRunner (dataSource); } /* * 创建数据源对象 * * */ /*和上面的dataSource一样:这样容器中就有了这个对象,就不会报错*/ @Bean(name = "dataSource") public DataSource createDataSource(){ try { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/eesy"); dataSource.setUser("root"); dataSource.setPassword("123456"); return dataSource; }catch (Exception e){ throw new RuntimeException(e); } } /* * 总结一下:原来JdbcConfig里面的东西是放在ConfigurationTest里面的,相当于,大模块是ConfigurationTest 然后 * 1. 大模块里面需要扫描包@ComponentScan({"com"})+@Configuration容器配置注解(当这样的时候,可以写,也可以不写这一个) * 并且配置ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class); * 2. 但是小模块分离出来之后JdbcConfig, * 大模块里面的就变为了这样@ComponentScan({"com","config"})+@Configuration(/或者/dbcConfig.class)其中一个 * 在小模块中的注解才能被扫描到JdbcConfig中的注解 * 3.我也知道这种方式很繁琐,比较容易乱,所以想要原来的方式,就用到这个注释:@import * 使用Import的注解就(细节:import可以传多个) * 大模块ConfigurationTest中:@Configuration+@ComponentScan("com")+@Import(JdbcConfig.class)+ ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class); * 就可以了 * * */ }
9.测试类:TestCode
package com.itheima; import com.domin.Account; import com.service.IAccountService; import config.ConfigurationTest; import config.JdbcConfig; import org.apache.commons.dbutils.QueryRunner; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import java.util.List; public class TestCode { @Test public void findAllAccount() { /*bean.xml 配置文件中*/ // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); /*配置类的注解方式使用的*/ ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class); IAccountService as = (IAccountService) ac.getBean("accountService"); /*类型要注意*/ List<Account> accounts = as.findAllAccount(); for (Account account :accounts){ System.out.println(account); } } @Test public void findAccountById() { // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); /*配置类的注解方式使用的*/ ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class); IAccountService as = (IAccountService) ac.getBean("accountService"); Account acc = as.findAccountById(4); System.out.println(acc); } @Test public void saveAccount() { // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class); IAccountService as = (IAccountService) ac.getBean("accountService"); Account acc = new Account(); acc.setName("lalala"); acc.setMoney((float)10000000.00); as.saveAccount(acc); System.out.println("执行成功"); } @Test public void updateAccount() { // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class); IAccountService as = (IAccountService) ac.getBean("accountService"); Account id = as.findAccountById(9); id.setName("zhou"); id.setMoney((float)100000.00); /*调用存放*/ as.updateAccount(id); } @Test public void deleteAccount() { /*bean.xml可以删了*/ // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class); IAccountService as = (IAccountService) ac.getBean("accountService"); as.deleteAccount(9); } } 注:检查单例和多例 10.QueryRunnerTest
package com.itheima; import config.ConfigurationTest; import org.apache.commons.dbutils.QueryRunner; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class QueryRunnerTest { @Test public void RunnerTest() { ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class); /*两种方式都可以,获取QueryRunner的对象runner1和runner2,查看是否单例还是多例*/ QueryRunner runner1 = ac.getBean("runner",QueryRunner.class); QueryRunner runner2 = (QueryRunner) ac.getBean("runner"); if (runner1 == runner2){ System.out.println("一样:"+runner1+"\n"+runner2); }else{ System.out.println("不一样:"+runner1+"\n"+runner2); } } /*执行sql语句的时候:在持久层的实现类,使用该方法可以会造成占用,所以变为多例*/ }
10.pom.xml依赖
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--spring框架依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!--C3P0依赖--> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!--jdbc依赖--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <!--dubcy依赖--> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency> <!-- mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency>
总结:在配置类中的常用注解
* 该类是一个配置类,它的作用和bean.xml是一样的 * spring中的新注解 * Configuration * 作用:指定当前类是一个配置类 * 细节: * 当配置类作为AnnotationConfigApplicationContext对象创建的参数的时候,该注解可以不写。 * (在测试类当中,直接通过类名.class传入,然后注解直接被扫描解读、、但是不绝对) * 为什么:当你独立开始使用jdbcConfig的时候,那么AnnotationConfigApplicationContext里面的配置文件 * 不再进行整个包的扫描,而是只单独解析类,所以,我们的@Configuration得注上,预防隔离开来的单独一个文件, * 所以进行扫描包的注解还是必须的 * * ComponentScan * 作用:用于通过注解指定spring在创建容器时要扫描的包。 * 属性: * value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。 * 我们使用此注解就等同于在XML中配置了:扫描包的语法 * <context:component-scan base-package="com"></context:component-scan> * Bean * 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中 * (容器是有键值对的[key,value],不写有默认值) * 属性: * name:用于指定bean的id。默认值是当前方法的名称 * 细节:当我们使用注解配置方法的时候,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象 * 查找的方式和Autowired是一样的 * Scope:作用域(单例singleton、多例prototype) * Import * 作用:用于导入其他的配置类 统一在大模块中导入,然后分别写小的子类模块就可以 * 属性: * value:用于指定其他配置类的字节码。 * 当我们使用Import的注解之后,有Import注解的类就是父配置类,而导入的都是子配置类 *
注:本人是小白,学习上的错误还希望大家多多指教,共同进步才好,加油加油