Spring封装的数据访问异常
与SQLException是一个Checked Exception不同,Spring定义的基本书籍访问异常DataAccessException是一个RuntimeException,DataAccessException继承自NestedRuntimeException,完整的保留了原始异常信息。
准备数据库环境
主键生成策略
1.数据库内置自增 (不好移植)
2.整形字段,程序控制主键自动增长 (集群时要严格控制同步)
3.UUID 根据计算机MAC地址和时间,随机计算生成,唯一 (128位整数,浪费空间)
JdbcTemplet
集成Hibernate
Hibernate管理Java类到数据库表的映射,提供了强大的基于对象的查询语句HQL,大幅减少数据库访问需要编写的代码的SQL语句,通过“方言”,最大限度降低了对特定数据库的依赖。
Hibernate还提供了系列复杂功能来简化数据库操作。
1.延迟加载,不一次取得所有相关联的对象,而是希望访问某个对象是再去数据库读取
2.主动抓取,允许在一个查询操作中就获得所有关联的对象,减少数据库连接次数
3.缓存
4.级联操作,外键关联的表,更新一个表时,需要同时更新其他表,级联删除 级联更新
集成Ibtais
集成JPA
Spring对JPA采用Adapter模式,使JPA和其他持久化机制(Hibernate Toplink JDO)拥有一致的编程模型。
与SQLException是一个Checked Exception不同,Spring定义的基本书籍访问异常DataAccessException是一个RuntimeException,DataAccessException继承自NestedRuntimeException,完整的保留了原始异常信息。
异常 | 定义 |
DataAccessException | SpringDAO异常体系跟类 |
ConcurrencyFailureException | 在多个并发访问时,无法乐观锁定或者获得数据库锁等 |
DataAccessResourceFailureException | 访问数据彻底失败,例如无法连接数据库 |
DataRetrievalFailureException | 无法获得指定数据,例如,根据主键无法查到相应记录 |
InvalidDataAccessResourceUsageException | 无效的数据访问方法,使用了语法错误的SQL语句 |
PermissionDeniedDataAccessException | 没有数据访问权限,例如,当前数据库登录用户无权访问特定表 |
UncategorizedDataAccessException | 无法归类的异常 |
准备数据库环境
- // HsqldbUtil类,创建Book表,并插入两条数据
- public static void startDatabase() {
- server = new Server();
- server.setDatabaseName(0, "test");
- server.setDatabasePath(0, "mem:bookstore");
- server.setLogWriter(null);
- server.setErrWriter(null);
- server.start();
- }
- <!-- 定义DataSource -->
- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
- <property name="url" value="jdbc:hsqldb:mem:bookstore" />
- <property name="username" value="sa" />
- <property name="password" value="" />
- </bean>
- <!-- 使用DriverManagerDataSource为了方便调试 实际中可方便更换为 -->
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
- <property name="jndiName" value="java:comp/env/jdbc/xxxDataSource"/>
- </bean>
主键生成策略
1.数据库内置自增 (不好移植)
2.整形字段,程序控制主键自动增长 (集群时要严格控制同步)
3.UUID 根据计算机MAC地址和时间,随机计算生成,唯一 (128位整数,浪费空间)
- public interface BookDao {
- List<Book> queryAll();
- List<Book> queryByAuthor(String author);
- void create(Book book);
- void update(Book book);
- void delete(String id);
- }
JdbcTemplet
- <!-- 注入dataSource -->
- <bean id="jdbcTemplateBookDao" class="example.chapter5.JdbcTemplateBookDao">
- <property name="dataSource" ref="dataSource" />
- </bean>
- public class JdbcTemplateBookDao extends JdbcDaoSupport implements BookDao {
- // ResultSet映射为Bean的方式
- class BookRowMapper implements RowMapper {
- public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
- Book book = new Book();
- book.setId(rs.getString("id"));
- book.setName(rs.getString("name"));
- book.setAuthor(rs.getString("author"));
- return book;
- }
- }
- @SuppressWarnings("unchecked")
- public List<Book> queryAll() {
- return getJdbcTemplate().query(
- "select * from Book",
- new BookRowMapper());
- }
- @SuppressWarnings("unchecked")
- public List<Book> queryByAuthor(String author) {
- return getJdbcTemplate().query(
- "select * from Book where author=?",
- new Object[] { author },
- new BookRowMapper());
- }
- public void create(Book book) {
- getJdbcTemplate().update(
- "insert into Book (id, name, author) values (?, ?, ?)",
- new Object[] {book.getId(), book.getName(), book.getAuthor()});
- }
- public void update(Book book) {
- getJdbcTemplate().update(
- "update Book set name=?, author=? where id=?",
- new Object[] {book.getName(), book.getAuthor(), book.getId()});
- }
- public void delete(String id) {
- getJdbcTemplate().update(
- "delete from Book where id=?",
- new Object[] {id});
- }
- }
集成Hibernate
Hibernate管理Java类到数据库表的映射,提供了强大的基于对象的查询语句HQL,大幅减少数据库访问需要编写的代码的SQL语句,通过“方言”,最大限度降低了对特定数据库的依赖。
Hibernate还提供了系列复杂功能来简化数据库操作。
1.延迟加载,不一次取得所有相关联的对象,而是希望访问某个对象是再去数据库读取
2.主动抓取,允许在一个查询操作中就获得所有关联的对象,减少数据库连接次数
3.缓存
4.级联操作,外键关联的表,更新一个表时,需要同时更新其他表,级联删除 级联更新
- <bean id="sessionFactory"
- class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="annotatedClasses">
- <list>
- <value>example.chapter5.Book</value>
- </list>
- </property>
- <property name="annotatedPackages">
- <list>
- <value>example.chapter5</value>
- </list>
- </property>
- <property name="hibernateProperties">
- <props>
- <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
- <prop key="hibernate.show_sql">true</prop>
- <prop key="hibernate.jdbc.fetch_size">10</prop>
- <prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
- </props>
- </property>
- <property name="eventListeners">
- <map>
- <entry key="pre-update">
- <bean class="org.hibernate.validator.event.ValidatePreUpdateEventListener" />
- </entry>
- <entry key="pre-insert">
- <bean class="org.hibernate.validator.event.ValidatePreInsertEventListener" />
- </entry>
- </map>
- </property>
- </bean>
- @Entity(name="Book")
- public class Book {
- // @Entity 作为数据库表映射 @Id 主键 @Transient不需要持久化字段
- private String id;
- private String name;
- private String author;
- @Id
- @Pattern(regex="[a-z0-9\\-]{36}", message="ID只能由英文字母,数字和-构成,长度为36个字符")
- public String getId() { return id; }
- public void setId(String id) { this.id = id; }
- public String getName() { return name; }
- public void setName(String name) { this.name = name; }
- public String getAuthor() { return author; }
- public void setAuthor(String author) { this.author = author; }
- }
- public class HibernateBookDao extends HibernateDaoSupport implements BookDao {
- @SuppressWarnings("unchecked")
- public List<Book> queryAll() {
- return getHibernateTemplate().find("select b from Book as b");
- }
- @SuppressWarnings("unchecked")
- public List<Book> queryByAuthor(String author) {
- return getHibernateTemplate().find("select b from Book as b where b.author=?", author);
- }
- public void create(Book book) {
- getHibernateTemplate().save(book);
- }
- public void delete(String id) {
- Book book = (Book) getHibernateTemplate().load(Book.class, id);
- getHibernateTemplate().delete(book);
- }
- public void update(Book book) {
- getHibernateTemplate().update(book);
- }
- }
集成Ibtais
- <bean id="iBatisBookDao" class="example.chapter5.IBatisBookDao">
- <property name="sqlMapClient">
- <bean class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
- <property name="configLocation" value="ibatis-sql-map-config.xml" />
- <property name="dataSource" ref="dataSource" />
- </bean>
- </property>
- </bean>
- public class IBatisBookDao extends SqlMapClientDaoSupport implements BookDao {
- @SuppressWarnings("unchecked")
- public List<Book> queryAll() {
- return getSqlMapClientTemplate().queryForList("queryAll");
- }
- @SuppressWarnings("unchecked")
- public List<Book> queryByAuthor(String author) {
- return getSqlMapClientTemplate().queryForList("queryByAuthor", author);
- }
- public void create(Book book) {
- getSqlMapClientTemplate().insert("create", book);
- }
- public void delete(String id) {
- getSqlMapClientTemplate().delete("delete", id);
- }
- public void update(Book book) {
- getSqlMapClientTemplate().update("update", book);
- }
- }
集成JPA
Spring对JPA采用Adapter模式,使JPA和其他持久化机制(Hibernate Toplink JDO)拥有一致的编程模型。
- <!--
- LocalEntityManagerFactoryBean 提供了标准的JPA初始化配置
- LocalContainerEntityManagerFactoryBean 更灵活,可以注入Spring管理的DataSource
- -->
- <bean id="entityManagerFactory"
- class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
- <property name="dataSource" ref="dataSource"/>
- <!-- Adapter 选择实现JPA的具体框架 -->
- <property name="jpaVendorAdapter">
- <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
- <property name="showSql" value="true" />
- <property name="generateDdl" value="false" />
- </bean>
- </property>
- </bean>
- <bean id="jpaTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
- <property name="entityManagerFactory" ref="entityManagerFactory" />
- </bean>
- <tx:annotation-driven transaction-manager="jpaTxManager" />
- public class JpaBookDao extends JpaDaoSupport implements BookDao {
- @SuppressWarnings("unchecked")
- public List<Book> queryAll() {
- return getJpaTemplate().find("select b from Book b");
- }
- @SuppressWarnings("unchecked")
- public List<Book> queryByAuthor(String author) {
- return getJpaTemplate().find("select b from Book b where b.author=?", new Object[] { author });
- }
- public void create(Book book) {
- getJpaTemplate().persist(book);
- }
- public void delete(String id) {
- Book book = getJpaTemplate().find(Book.class, id);
- getJpaTemplate().remove(book);
- }
- public void update(Book book) {
- getJpaTemplate().merge(book);
- }
- }