使用 spring 的 IoC 的实现账户的CRUD(增删改查)
技术要求:
- 使用 spring 的 IoC 实现对象的管理
- 使用 DBAssit 作为持久层解决方案
- 使用 c3p0 数据源
第一步:导入相应依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
第二步:创建数据库和编写实体类
REATE TABLE account (
`id int(11) NOT NULL,
name varchar(40) DEFAULT NULL,
money float DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
insert into account(id,name,money) values(1,'aaa',1000);
insert into account(id,name,money) values(2,'bbb',1000);
insert into account(id,name,money) values(3,'ccc',1000);
//账户实体类
package zlb.demo03.domain;
public class Account {
private Integer id;
private String name;
private Double money;
public Account() {
}
public Account(Integer id, String name, double money) {
this.id = id;
this.name = name;
this.money = 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 double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
2. 编写持久层代码
/*
* 账户的持久层接口
* */
public interface AccountDao {
/*查询所有
* */
List<Account> findAllAccount();
//根据id单个查询
Account findAccount(Integer accountId);
//插入
void saveAccount( Account account)
//更新
void updateAccount(Account account);
//根据id删除一个
void deleteAccount(Integer accountId);
}
/*
* 持久层实现类
* */
public class AccountDaoImpl implements AccountDao {
private QueryRunner runner;
public void setRunner(QueryRunner runner) {
this.runner = runner;
}
public List<Account> findAllAccount() {
try {
return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Account findAccount(Integer accountId) {
try {
return runner.query("select * from account where id=?" , new BeanHandler<Account>(Account.class),accountId);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void saveAccount(Account account) {
try {
runner.update("insert into account(name,money,id)values(?,?,?)" ,account.getName(),account.getMoney(),account.getId() );
} catch (SQLException e) {
new RuntimeException(e);
}
}
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);
}
}
public void deleteAccount(Integer accountId) {
try {
runner.update("delete from account where id=?" ,accountId);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
3.编写业务层代码
/*
* *业务层接口
*/
public interface AccountService {
List<Account> findAllAccount();
Account findAccount(Integer accountId);
void saveAccount( Account account) throws SQLException;
void updateAccount(Account account);
void deleteAccount(Integer accountId);
}
public class AccountServiceImpl implements AccountService{
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public List<Account> findAllAccount() {
return accountDao.findAllAccount();
}
public Account findAccount(Integer accountId) {
return accountDao.findAccount(accountId);
}
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
public void deleteAccount(Integer accountId) {
accountDao.deleteAccount(accountId);
}
}
4.创建并编写配置文件
<?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.xsd ">
<!--配置service-->
<bean id="accountService" class="zlb.demo03.service.AccountServiceImpl" >
<property name="accountDao" ref="accountDao"></property>
</bean>
<!--配置dao-->
<bean id="accountDao" class="zlb.demo03.dao.Impl.AccountDaoImpl">
<property name="runner" ref="runner"></property>
</bean>
<!--配置QueryRunner-->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!--配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy"></property>
<property name="user" value="root"></property>
<property name="password" value="151630"></property>
</bean>
</beans>
5.测试类代码
ublic class TestApp {
@Test
//查所有
public void testFindAll() {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
AccountService accountService =(AccountService) context.getBean("accountService");
List<Account> allAccount = accountService.findAllAccount();
for (Account account : allAccount) {
System.out.println(account);
}
}
@Test
//查一个
public void testFindOne() {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
AccountService accountService =(AccountService) context.getBean("accountService");
Account account = accountService.findAccount(2);
System.out.println(account);
}
@Test
//添加账户
public void testInsert() throws SQLException {
Account account=new Account(35,"java",5000);
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
AccountService accountService =(AccountService) context.getBean("accountService");
accountService.saveAccount(account);
}
@Test
//更新账户
public void testUpdate() {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
AccountService accountService =(AccountService) context.getBean("accountService");
Account account = accountService.findAccount(2);
account.setName("hello");
account.setMoney(6000);
accountService.updateAccount(account);
}
@Test
//删除账户
public void testDelete() {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
AccountService accountService =(AccountService) context.getBean("accountService");
accountService.deleteAccount(2);
}
}
上述是通过xml配置。
下面通过注解配置实现
1.将上面xml文件中如下代码删除
<!--配置service-->
<bean id="accountService" class="zlb.demo03.service.AccountServiceImpl" >
<property name="accountDao" ref="accountDao"></property>
</bean>
<!--配置dao-->
<bean id="accountDao" class="zlb.demo03.dao.Impl.AccountDaoImpl">
<property name="runner" ref="runner"></property>
</bean>
2.在配置文件添加下面代码(万分注意)
<context:component-scan base-package=“zlb.demo03”></context:component-scan>
3.添加如下注解
新注解说明
@Configuration
作用:
用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用
AnnotationApplicationContext(有@Configuration 注解的类.class)。
属性:
value:用于指定配置类的字节码
@ComponentScan
作用:
用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package=“com.itheima”/>是一样的。
属性:
basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。
@Bean
作用:
该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
属性:
name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
下面用这三个注解让我们脱离xml配置文件,对上面案例进行实现
1.新建一个配置类
@Configuration
@ComponentScan("zlb.demo03")
public class ConfigClass {
public class JdbcConfig {
/**
* 创建一个数据源,并存入 spring 容器中
*/
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser("root");
ds.setPassword("151630");
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy");
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
} }
/**
* 创建一个 Query,并且也存入 spring 容器中
*/
@Bean(name="runner")
public QueryRunner createQuery(DataSource dataSource) {
return new QueryRunner(dataSource);
} }
}
把
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
换成
ApplicationContext context=newAnnotationConfigApplicationContext(ConfigClass.class);
@Import注解
作用:用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。
属性:value[]:用于指定其他配置类的字节码。
当我们使用Import注解之后,有Import注解的就是父配置类,而导入的都是子配置类。
/父配置类
//@Configuration
@ComponentScan("zlb.demo03")
@Import(JdbcConfig.class)
public class ConfigClass {
/* public class JdbcConfig {
*//**
* 创建一个数据源,并存入 spring 容器中
*//*
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser("root");
ds.setPassword("151630");
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy");
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
} }
*//**
* 创建一个 Query,并且也存入 spring 容器中
*//*
@Bean(name="runner")
public QueryRunner createQuery(DataSource dataSource) {
return new QueryRunner(dataSource);
} }*/
}
//子配置类
@Configuration
public class JdbcConfig {
/**
* 创建一个数据源,并存入 spring 容器中
*/
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser("root");
ds.setPassword("151630");
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy");
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
} }
/**
* 创建一个 Query,并且也存入 spring 容器中
*/
@Bean(name="runner")
public QueryRunner createQuery(DataSource dataSource) {
return new QueryRunner(dataSource);
} }
//把
ApplicationContext context=newAnnotationConfigApplicationContext(ConfigClass.class);
换成
ApplicationContext context=new AnnotationConfigApplicationContext(ConfigClass.class, JdbcConfig.class);
通过上述代码也可实现
@PropertySource
作用:
用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信operties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
属性:value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
@Configuration
@ComponentScan("zlb.demo03")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbc.properties")
public class ConfigClass {
/* public class JdbcConfig {
*//**
* 创建一个数据源,并存入 spring 容器中
*//*
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser("root");
ds.setPassword("151630");
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy");
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
} }
*//**
* 创建一个 Query,并且也存入 spring 容器中
*//*
@Bean(name="runner")
public QueryRunner createQuery(DataSource dataSource) {
return new QueryRunner(dataSource);
} }*/
}
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;
@Bean(name="dataSource")
public DataSource createDataSource() {
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setUser(username);
ds.setPassword(password);
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
return ds;
} catch (Exception e) {
throw new RuntimeException(e);
} }
@Bean(name="runner")
public QueryRunner createQuery(DataSource dataSource) {
return new QueryRunner(dataSource);
} }
jdbc.peoperties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=151630
Spring 整合 Junit
1.加入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
使用@RunWith 注解替换原有运行器
使用@ContextConfiguration 指定 spring 配置文件的位置
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ConfigClass.class)
public class TestApp {
@Autowired
private AccountService accountService;
@Test
//查所所有
public void testFindAll() {
List<Account> allAccount = accountService.findAllAccount();
for (Account account : allAccount) {
System.out.println(account);
}
}
}