1、表(這裏用mysql,數據庫名爲yiibai)html
CREATE TABLE `customer` ( `CUST_ID` int(10) UNSIGNED NOT NULL, `NAME` varchar(100) NOT NULL, `AGE` int(10) UNSIGNED NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `customer` ADD PRIMARY KEY (`CUST_ID`);
2、不用JdbcTemplate的狀況java
表的實體類Customermysql
package com.yiibai.springjdbc.bean; public class Customer { int custId; String name; int age; public Customer(int custId, String name, int age) { super(); this.custId = custId; this.name = name; this.age = age; } public int getCustId() { return custId; } public void setCustId(int custId) { this.custId = custId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Customer [custId=" + custId + ", name=" + name + ", age=" + age + "]"; } }
DAO接口spring
package com.yiibai.springjdbc.dao; import java.util.List; import com.yiibai.springjdbc.bean.Customer; public interface CustomerDAO { public void insert(Customer customer); public Customer findByCustomerId(int custId); public List<Customer> queryCustomer() throws Exception ; }
DAO實現(不用JdbcTemplate)sql
package com.yiibai.springjdbc.daoimpl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import javax.sql.DataSource; import com.yiibai.springjdbc.bean.Customer; import com.yiibai.springjdbc.dao.CustomerDAO; public class CustomerImplDAO implements CustomerDAO { private DataSource dataSource; @Override public void insert(Customer customer) { // TODO 自動生成的方法存根 String sql = "INSERT INTO customer " + "(CUST_ID, NAME, AGE) VALUES (?, ?, ?)"; Connection conn = null; try { conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, customer.getCustId()); ps.setString(2, customer.getName()); ps.setInt(3, customer.getAge()); ps.executeUpdate(); ps.close(); } catch (SQLException e) { throw new RuntimeException(e); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { } } } } @Override public Customer findByCustomerId(int custId) { // TODO 自動生成的方法存根 String sql = "SELECT * FROM customer WHERE CUST_ID = ?"; Connection conn = null; try { conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, custId); Customer customer = null; ResultSet rs = ps.executeQuery(); if (rs.next()) { customer = new Customer(rs.getInt("CUST_ID"), rs.getString("NAME"), rs.getInt("Age")); } rs.close(); ps.close(); return customer; } catch (SQLException e) { throw new RuntimeException(e); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { } } } } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public List<Customer> queryCustomer() throws Exception { // TODO 自動生成的方法存根 Connection conn = dataSource.getConnection(); String sql = "Select c.CUST_ID, c.NAME, c.AGE from customer c"; System.out.println(sql); Statement smt = conn.createStatement(); ResultSet rs = smt.executeQuery(sql); List<Customer> list = new ArrayList<Customer>(); while (rs.next()) { int cID = rs.getInt("CUST_ID"); String cName = rs.getString("NAME"); int cAge = rs.getInt("AGE"); Customer cust = new Customer(cID, cName, cAge); list.add(cust); } return list; } }
配置文件spring-dao.xml spring-datasource.xml spring-module.xml都放置在(特別重要)包com.yiibai.springjdbc下面:數據庫
spring-datasource.xmlapache
<?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"> <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/yiibai?useSSL=false" /> <property name="username" value="your-user" /> <property name="password" value="your-passwd" /> </bean> </beans>
也能夠使用DBCP鏈接池來配置數據源(須要導入commons-dbcp-1.4.jar包)編程
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/yiibai?useSSL=false" /> <property name="username" value="your-name" /> <property name="password" value="your-passwd" /> </bean>
這裏須要修改用戶密碼來適應你的數據庫環境session
spring-dao.xmlmybatis
<?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"> <bean id="customerDAO" class="com.yiibai.springjdbc.daoimpl.CustomerImplDAO"> <property name="dataSource" ref="dataSource" /> </bean> </beans>
spring-module.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Using Mysql datasource --> <import resource="spring-datasource.xml" /> <import resource="spring-dao.xml" /> </beans>
測試(主)類
package com.yiibai.springjdbc; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.yiibai.springjdbc.bean.Customer; import com.yiibai.springjdbc.dao.CustomerDAO; public class CustTest { private static ApplicationContext ctx; public static void main(String[] args) throws Exception { ctx = new ClassPathXmlApplicationContext("com/yiibai/springjdbc/spring-module.xml"); CustomerDAO customerDAO = (CustomerDAO) ctx.getBean("customerDAO"); Customer customer = new Customer(1, "yiibai",29); customerDAO.insert(customer); Customer customer1 = customerDAO.findByCustomerId(1); System.out.println(customer1); List<Customer> custList = customerDAO.queryCustomer(); for(Customer cs : custList){ System.out.println("Customer ID " + cs.getCustId()); System.out.println("Customer Name " + cs.getName()); System.out.println("Customer Age" + cs.getAge()); System.out.println("----------------------------"); } } }
運行結果:表customer加了一條記錄,並輸出以下信息:
(執行前把表customer中id爲1的記錄刪除,否則插入異常)
3、使用 JdbcTemplate、JdbcDaoSupport實現
Customer和DAO接口不變,主要變化是DAO實現:CustomerImplDAO類改成JdbcCustomerDAO
package com.yiibai.springjdbc.daoimpl; import java.util.List; import org.springframework.jdbc.core.support.JdbcDaoSupport; import com.yiibai.springjdbc.bean.Customer; import com.yiibai.springjdbc.bean.CustomerRowMapper; import com.yiibai.springjdbc.dao.CustomerDAO; public class JdbcCustomerDAO extends JdbcDaoSupport implements CustomerDAO { @Override public void insert(Customer customer) { // TODO 自動生成的方法存根 String sql = "INSERT INTO customer " + "(CUST_ID, NAME, AGE) VALUES (?, ?, ?)"; getJdbcTemplate().update(sql, new Object[] { customer.getCustId(), customer.getName(),customer.getAge() }); } @Override public Customer findByCustomerId(int custId) { // TODO 自動生成的方法存根 /* * 這種寫法也能夠 String sql = "SELECT * FROM customer WHERE CUST_ID = '"+custId+"' "; return getJdbcTemplate().queryForObject(sql,new CustomerRowMapper()); */ String sql = "SELECT * FROM customer WHERE CUST_ID = ?"; return getJdbcTemplate().queryForObject(sql,new Object[] { custId },new CustomerRowMapper()); } @Override public List<Customer> queryCustomer() throws Exception { // TODO 自動生成的方法存根 String sql = "SELECT * FROM customer"; return getJdbcTemplate().query(sql, new CustomerRowMapper()); } }
須要說明2點:
一、本實現繼承JdbcDaoSupport,而 JdbcDaoSupport定義了 JdbcTemplate和DataSource 屬性,只需在配置文件中注入DataSource 便可,而後會建立jdbcTemplate的實例,沒必要像前面的實現CustomerImplDAO那樣,須要顯式定義一個DataSource成員變量。
二、這裏出現了CustomerRowMapper類:原本應該這樣寫的queryForObject(sql,Customer.class);但Spring並不知道如何將結果轉成Customer.class。因此須要寫一個CustomerRowMapper 繼承RowMapper接口 ,其代碼以下:
package com.yiibai.springjdbc.bean; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; public class CustomerRowMapper implements RowMapper<Customer> { @Override public Customer mapRow(ResultSet rs, int rowNum) throws SQLException { // TODO 自動生成的方法存根 return new Customer(rs.getInt("CUST_ID"),rs.getString("NAME"),rs.getInt("AGE")); } }
文件spring-dao.xml裏bean的定義修改成(變化的是class):
<bean id="customerDAO" class="com.yiibai.springjdbc.daoimpl.JdbcCustomerDAO"> <property name="dataSource" ref="dataSource" /> </bean>
其餘配置文件和主類都不變、運行結果少了Select c.CUST_ID, c.NAME, c.AGE from customer c
,這是由於CustomerImplDAO版本人爲地插入一句 System.out.println(sql);以示和JDBC模板實現版本JdbcCustomerDAO的區別。
能夠看出採用JDBC模板大大簡化代碼。
4、 HibernateTemplate、HibernateDaoSupport實現版本
CustomerImplDAO類改成HibCustomerDao
package com.yiibai.springjdbc.daoimpl; import java.util.List; import org.springframework.orm.hibernate4.support.HibernateDaoSupport; import com.yiibai.springjdbc.bean.Customer; import com.yiibai.springjdbc.dao.CustomerDAO; public class HibCustomerDao extends HibernateDaoSupport implements CustomerDAO { @Override public void insert(Customer customer) { // TODO 自動生成的方法存根 this.getHibernateTemplate().save(customer); } @Override public Customer findByCustomerId(int custId) { // TODO 自動生成的方法存根 //或find("from Customer where CUST_ID = ?",custId).get(0); return (Customer) getHibernateTemplate().get(Customer.class, custId); } @Override public List<Customer> queryCustomer() throws Exception { // TODO 自動生成的方法存根 return (List<Customer>) getHibernateTemplate().find("from com.yiibai.springjdbc.bean.Customer"); } }
配置文件修改就比較複雜了:要配置SessionFactory、transactionManager、transactionInterceptor等。
,另外要在包com.yiibai.springjdbc.bean增長表對象Customer的Hibernate映射文件Customer.hbm.xml以供配置hibernate SessionFactory使用:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.yiibai.springjdbc.bean"> <class name="Customer" table="customer"> <id name="custId" type="java.lang.Integer"> <column name="CUST_ID" /> <generator class="native"/> </id> <property name="name" unique="true" type="java.lang.String"> <column name="NAME" /> </property> <property name="age" unique="true" type="java.lang.Integer"> <column name="AGE" /> </property> </class> </hibernate-mapping>
修改後的spring-dao.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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd"> <!-- 把數據源注入給Session工廠 --> <bean id="custsessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource1" /> <property name="mappingResources"> <list> <value>com/yiibai/springjdbc/bean/Customer.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.generate_statistics">true</prop> <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop> </props> </property> </bean> <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="custsessionFactory" /> </bean> <!--define bean of transaction interceptor --> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager" /> <property name="transactionAttributes"> <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*Dao</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean> <bean id="customerDAO" class="com.yiibai.springjdbc.daoimpl.HibCustomerDao"> <property name="sessionFactory" ref="custsessionFactory" /> </bean> </beans>
若是僅配置SessionFactory、而不配置transactionManager、transactionInterceptor,查詢沒問題,而插入不行,會出現下面的異常:
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
有沒有辦修改SessionFactory的設置解決這個問題,求高人指點。
hibernate配置也能夠用註解方式(無需Customer.hbm.xml):
修改Customer類以下( custId必需要改CUST_ID,和表格字段名徹底一致):
package com.yiibai.springjdbc.bean; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "customer") public class Customer { @Id int CUST_ID; String name; int age; public Customer() { super(); // TODO 自動生成的構造函數存根 } public Customer(int custId, String name, int age) { super(); this.CUST_ID = custId; this.name = name; this.age = age; } public int getCustId() { return CUST_ID; } public void setCustId(int custId) { this.CUST_ID = custId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Customer [custId=" + CUST_ID + ", name=" + name + ", age=" + age + "]"; } }
spring-dao.xml文件的custsessionFactory配置中
<property name="mappingResources"> <list> <value>com/yiibai/springjdbc/bean/Customer.hbm.xml</value> </list> </property>
改成:
<property name="annotatedClasses"> <list> <value>com.yiibai.springjdbc.bean.Customer</value> </list> </property>
另外經實踐.hbm.xml版本(注射方式則不會,我也沒搞明白其中的道理)的CUST_ID不是根據insert(customer)傳遞過來參數的值,而是會根據數據庫表customer當前的ID「指針」;好比傳遞過來的參數是Customer(1, "yiibai",29),插入後有可能變(3, "yiibai",29)。
可用下面命令來複位ID「指針」
mysql> use yiibai; mysql> ALTER TABLE customer AUTO_INCREMENT=0;
這樣新插入的CUST_ID值就是:最後一條記錄CUST_ID+1。
5、mybatis、SqlSessionDaoSupport版本
爲了簡單起見,使用註解方式使用mybatis(和XML配置能夠混用的,詳見該文),重寫了dao接口放在com.yiibai.springjdbc.mybatisdao包下,爲保證主類代碼不變原來的接口CustomerDAO繼續使用。
package com.yiibai.springjdbc.mybatisdao; import java.util.List; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import com.yiibai.springjdbc.bean.Customer; public interface ICustomer { @Insert("insert into customer(CUST_ID,name,age) values(#{CUST_ID},#{name}, #{age})") public void insert(Customer customer); @Select("select * from customer where CUST_ID= #{CUST_ID}") public Customer findByCustomerId(int custId); @Select("select * from customer") public List<Customer> queryCustomer(); @Delete("delete from customer where CUST_ID=#{CUST_ID}") public int deleteCustomerById(int id); }
全部的sql操做由該接口完成,後面的DAO實現類MybatisCustImpDao,實際上僅僅調用該接口的方法:
package com.yiibai.springjdbc.daoimpl; import java.util.List; import org.mybatis.spring.support.SqlSessionDaoSupport; import com.yiibai.springjdbc.bean.Customer; import com.yiibai.springjdbc.dao.CustomerDAO; import com.yiibai.springjdbc.mybatisdao.ICustomer; public class MybatisCustImpDao extends SqlSessionDaoSupport implements CustomerDAO { @Override public void insert(Customer customer) { // TODO 自動生成的方法存根 this.getSqlSession().getMapper(ICustomer.class).insert(customer);; } @Override public Customer findByCustomerId(int custId) { // TODO 自動生成的方法存根 return this.getSqlSession().getMapper(ICustomer.class).findByCustomerId(custId); } @Override public List<Customer> queryCustomer() throws Exception { // TODO 自動生成的方法存根 return this.getSqlSession().getMapper(ICustomer.class).queryCustomer(); } }
mybatis的配置文件mybatiscust.xml放在com.yiibai.springjdbc下
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <typeAlias alias="Customer" type="com.yiibai.springjdbc.bean.Customer" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/yiibai?useSSL=false" /> <property name="username" value="your-user" /> <property name="password" value="your-passwd" /> </dataSource> </environment> </environments> <mappers> <!-- XML的方式 註冊映射配置文件--> <!-- <mapper resource="com/yiibai/springjdbc/bean/CustMybatis.xml" /> --> <!--接口的方式 註冊接口--> <mapper class="com.yiibai.springjdbc.mybatisdao.ICustomer"/> </mappers> </configuration>
bean必須注入sqlSessionFactory或sqlSessionTemplate。仍是在中spring-dao.xml配置:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:com/yiibai/springjdbc/mybatiscust.xml" /> </bean> <bean id="CustomerDao" class="com.yiibai.springjdbc.daoimpl.MybatisCustImpDao"> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>
或
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:com/yiibai/springjdbc/mybatiscust.xml" /> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg ref="sqlSessionFactory" /> </bean> <bean id="CustomerDao" class="com.yiibai.springjdbc.daoimpl.MybatisCustImpDao"> <property name="sqlSessionTemplate" ref="sqlSession" /> </bean>
主程序仍是不變。
參考:
Spring Mybatis實例SqlSessionDaoSupport混用xml配置和注解
HibernateTemplate、HibernateDaoSupport兩種方法實現增刪
Spring JdbcTemplate+JdbcDaoSupport實例
如何經過繼承SqlSessionDaoSupport來編寫DAO(一)
項目的代碼和依賴包都在這裏,下後解壓到eclipse的workspace導入選擇import Porojects from File System or Archive。