JDBCTemplate執行增刪改查(CDUR)操作


1、JdbcTemplate簡介

(1)Spring提供的一個操作數據庫的技術JdbcTemplate,是對Jdbc的封裝。語法風格非常接近DBUtil。

  • JdbcTemplate可以直接操作數據庫,加快效率,而且學這個JdbcTemplate也是為聲明式事務做准備,畢竟要對數據庫中的數據進行操縱!
  • JdbcTemplate中並沒有提供一級緩存,以及類與類之間的關聯關系!就像是spring提供的一個DBUtils。
  • Spring對數據庫的操作使用JdbcTemplate來封裝JDBC,結合Spring的注入特性可以很方便的實現對數據庫的訪問操作。使用JdbcTemplate可以像JDBC一樣來編寫數據庫的操作代碼

(2)為啥要使用Jdbc_template進行開發呢?

  • Spring對數據庫的操作在jdbc上面做了深層次的封裝,使用spring的注入功能,可以把DataSource注冊到JdbcTemplate之中。
  • Spring提供的JdbcTemplate對jdbc做了封裝,大大簡化了數據庫的操作。

找到Spring JdbcTemplate源碼,可以看到如下方法:

Connection con = DataSourceUtils.getConnection(getDataSource());

如果直接使用JDBC的話,需要我們加載數據庫驅動、創建連接、釋放連接、異常處理等一系列的動作;繁瑣且代碼看起來不直觀。

此外,Spring提供的JdbcTempate能直接數據對象映射成實體類,不再需要獲取ResultSet去獲取值/賦值等操作,提高開發效率;

如下:return (User) jdbcTemplate.queryForObject("select * from tb_test1 where id = 100", User.class)

(3)配置環境

①導入jar包

    • commons-logging-1.1.3.jar
    • spring-aop-4.0.0.RELEASE.jar //注解會使用到的包
    • spring-beans-4.0.0.RELEASE.jar
    • spring-context-4.0.0.RELEASE.jar
    • spring-core-4.0.0.RELEASE.jar
    • spring-expression-4.0.0.RELEASE.jar

②在IOC容器中配置數據源

<!-- 加載properties文件中 信息 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置數據源 -->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.passowrd}"></property>
    <property name="jdbcUrl" value="${jdbc.url}"></property>
    <property name="driverClass" value="${jdbc.driver}"></property>
</bean>

其中jdbc.properties文件內容:

  • jdbc.user=root
  • jdbc.passowrd=mysql
  • jdbc.url=jdbc:mysql://localhost:3306/test
  • jdbc.driver=com.mysql.jdbc.Driver

③在IOC容器(applicationContext.xml)中配置JdbcTemplate對象的bean,並將數據源對象裝配到JdbcTemplate對象中

<!-- 配置JdbcTemplate對應的bean, 並裝配dataSource數據源屬性-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="comboPooledDataSource"></property>
</bean>

2、案例演示

(1)首先,新建數據庫 jdbc_template,新建表 employee,並插入幾條測試數據

USE `jdbc_template`;
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
  `emp_id` int(11) NOT NULL AUTO_INCREMENT,
  `emp_name` char(100) DEFAULT NULL,
  `salary` double DEFAULT NULL,
  PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=gb2312;

將數據庫連接信息改為:jdbc.url=jdbc:mysql://localhost:3306/jdbc_template

(2)在bean包下新建 Employee.java

 1 public class Employee {
 2     private Integer emp_id;
 3     private String emp_name;
 4     private Double salary;
 5     public Employee() {
 6         super();
 7     }
 8     public Employee(Integer emp_id, String emp_name, double salary) {
 9         super();
10         this.emp_id = emp_id;
11         this.emp_name = emp_name;
12         this.salary = salary;
13     }
14     public int getEmp_id() {
15         return emp_id;
16     }
17     public void setEmp_id(int emp_id) {
18         this.emp_id = emp_id;
19     }
20     public String getEmp_name() {
21         return emp_name;
22     }
23     public void setEmp_name(String emp_name) {
24         this.emp_name = emp_name;
25     }
26     public double getSalary() {
27         return salary;
28     }
29     public void setSalary(double salary) {
30         this.salary = salary;
31     }
32     @Override
33     public String toString() {
34         return "Employee [emp_id=" + emp_id + ", emp_name=" + emp_name + ", salary=" + salary + "]";
35     }
36 }
Employee.java

(3)新建JUnit測試類進行測試 TestJdbcTemp.java

public class TestJdbcTemp {
    //聲明兩個對象ioc和JdbcTemplate
    private ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
    private JdbcTemplate template = ioc.getBean(JdbcTemplate.class);
}

① 測試數據源 DataSource 

@Test
public void testDataSource() {
    DataSource bean = ioc.getBean(DataSource.class);
    try {
        System.out.println(bean.getConnection());//com.mchange.v2.c3p0.impl.NewProxyConnection@223aa2f7
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

② 將emp_id=5的記錄的salary字段更新為1300.00【更新操作】

@Test
public void testUpdate() {
    String sql = "UPDATE employee SET salary = ? WHERE emp_id = ?";
    template.update(sql, 1300, 5);//第一個是sql語句,后面的按着順序傳入參數即可,update方法能接收的可變參數!
}

可以看到,該操作不用我們自己再去獲取數據庫連接信息了,而是直接傳遞sql語句及其參數就可以了!

③ 批量插入

@Test
public void testBatch() {
    String sql = "INSERT INTO employee(`emp_name`,`salary`) VALUES(?,?)";
    // 執行sql語句需要傳遞的參數
    List<Object[]> list = new ArrayList<Object[]>();
    list.add(new Object[] { "Tom2015", 1000 });
    list.add(new Object[] { "Tom2016", 2000 });
    list.add(new Object[] { "Tom2017", 3000 });
    template.batchUpdate(sql, list);
}

④ 查詢emp_id=5的數據庫記錄,封裝為一個Java對象返回,

分析:封裝為一個對象返回的話,首先我們需要有一個與數據表對應的實體類!

@Test
public void testFindById(){
    //需要注意的是:sql語句中的別名要與對應實體類的屬性名保持一致!ps:這里不用別名也可以
    String sql = "SELECT emp_id AS emp_id,emp_name AS emp_name,salary FROM employee WHERE emp_id=?";
    //RowMapper是一個接口,我們使用其子類,把查出來的數據封裝成一個bean對象
    RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<Employee>(Employee.class);
    //最后一個參數是可變參數,用於向sql語句中依次傳遞參數!
    Employee employee = template.queryForObject(sql, rowMapper, 5);
    System.out.println(employee);//Employee [emp_id=5, emp_name=Kasier, salary=1300.0]
}

⑤ 查詢salary>4000的數據庫記錄,封裝為List集合返回

@Test
public void testEmployeeList(){
    //需要注意的是:sql語句中的別名要與對應實體類的屬性名保持一致!ps:這里不用別名也可以
    String sql = "SELECT emp_id AS emp_id,emp_name AS emp_name,salary FROM employee WHERE salary > ?";
    //RowMapper是一個接口,這里我們使用其子類,把查出來的數據封裝成一個bean對象
    RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<Employee>(Employee.class);
    //該query方法查詢出來的是一個list列表,query方法的最后一個參數是可變參數!
    List<Employee> list = template.query(sql, rowMapper, 4000);
    for (Employee employee : list) {
        System.out.println(employee);
        //Employee [emp_id=1, emp_name=Susan, salary=5000.23]
        //Employee [emp_id=2, emp_name=Julian, salary=4234.77]
        //Employee [emp_id=3, emp_name=Papu, salary=9034.51]
        //Employee [emp_id=4, emp_name=Babala, salary=8054.33]
        //Employee [emp_id=6, emp_name=Owen, salary=7714.11]
    }
}

查詢結果是一個實體還是一個list列表是靠template對象的不同方法實現的!

⑥ 查詢最大salary【返回單值】

@Test
public void testMaxSalary(){
    String sql = "SELECT MAX(salary) FROM employee";
    //需要指定返回值的類型,而且類型必須是包裝類型,可帶可變參數
    Double maxSalary = template.queryForObject(sql, Double.class);
    System.out.println(maxSalary);//9034.51
}

⑦ 使用帶有具名參數的SQL語句插入一條員工記錄,並以Map形式傳入參數值

具名參數:是指基於名稱的,前面我們使用的都是用?作為占位符,然后是使用基於位置的

如果要使用具名參數的sql語句就必須在spring配置文件中配置NamedParameterJdbcTemplat這個模板類,而不能使用原來的JdbcTemplate,因為JdbcTemplate不能完成這樣的任務!

在 applicationContext.xml 中新增配置信息

<!-- 加載properties文件中的信息 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 配置數據源 -->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}"></property>
    <property name="jdbcUrl" value="${jdbc.url}"></property>
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置JdbcTemplate對應的bean, 並裝配dataSource數據源屬性-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="comboPooledDataSource"></property>
</bean>
<!-- 為了執行帶有具名參數的SQL語句,需要配置NamedParameterJdbcTemplate -->
<!-- 該NamedParameterJdbcTemplate類沒有無參構造器,需要傳入JdbcTemplate對象或者數據源對象[DataSource] -->
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    <!-- 不能使用property標簽配置哦 -->
    <constructor-arg ref="jdbcTemplate"></constructor-arg>
</bean>

測試

@Test
public void testParam(){
    String sql="INSERT INTO employee VALUES(null,:paramName,:paramSalary)";
    Map<String,Object> paramMap = new HashMap<String,Object>();
    paramMap.put("paramName","LiMing" );
    paramMap.put("paramSalary",1000);
    namedJdbcTemplate.update(sql, paramMap);
}

⑧ 重復實驗 ⑦,以 SqlParameterSource 形式傳入參數值

@Test
public void testParameterSource(){
    String sql="INSERT INTO employee(`emp_name`,`salary`) VALUES(:emp_name,:salary)";
    //該BeanPropertySqlParameterSource類構造器需要一個對象參數,該對象參數是一個封裝了sql語句參數的對象!
    //此時要求對象的屬性名要和sql中的參數名保持一致!這里我們使用Employee對象來完成
    Employee employee= new Employee(null, "Danny", 1500);
    //以實體對象的形式封裝具名參數和值
    SqlParameterSource source = new BeanPropertySqlParameterSource(employee);
    namedJdbcTemplate.update(sql, source);
}

⑨ 創建 EmployeeDao,自動裝配 JdbcTemplate 對象

創建 EmployeeDao 類

@Repository//加載到IOC容器
public class EmployeeDao {
    @Autowired//注入JdbcTemplate對象
    private JdbcTemplate jdbcTemplate;
    //更新工資,加1000元
    public void updateSaraly(Integer id){
        String sql = "update employee set salary=salary+1000 where emp_id=?";
        jdbcTemplate.update(sql, id);
    }
    //查詢所有員工信息
    public List<Employee> findAll(){
        String sql = "select * from employee";
        RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<Employee>(Employee.class);
        return jdbcTemplate.query(sql, rowMapper);
    }
}

配置spring的配置文件的配置文件 applicationContext.xml

<!-- 配置掃描的包 -->
<context:component-scan base-package="com.bwlu.dao"></context:component-scan>
<!-- 加載properties文件中的信息 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置數據源 -->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.passowrd}"></property>
    <property name="jdbcUrl" value="${jdbc.url}"></property>
    <property name="driverClass" value="${jdbc.driver}"></property>
</bean>
<!-- 配置JdbcTemplate對應的bean,並裝配dataSource數據源屬性-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="comboPooledDataSource"></property>
</bean>

測試Dao

@Test
public void testUpdateSalary(){
    EmployeeDao employeeDao = ioc.getBean(EmployeeDao.class);
    employeeDao.updateSaraly(11);
}
@Test
public void testFindAll(){
    EmployeeDao employeeDao = ioc.getBean(EmployeeDao.class);
    List<Employee> list = employeeDao.findAll();
    for (Employee employee : list) {
        System.out.println(employee);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM