`

Spring数据访问策略

阅读更多
Spring封装的数据访问异常
与SQLException是一个Checked Exception不同,Spring定义的基本书籍访问异常DataAccessException是一个RuntimeException,DataAccessException继承自NestedRuntimeException,完整的保留了原始异常信息。

异常定义
DataAccessExceptionSpringDAO异常体系跟类
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);
    }
}
分享到:
评论

相关推荐

    Spring下使用策略模式

    在Spring框架中,策略模式常用于处理不同策略的配置和注入,例如AOP切面的实现方式、数据访问策略等。 首先,我们需要理解Spring中的Bean工厂,它是Spring的核心,负责创建、管理和维护Bean。在策略模式中,Bean...

    使用Spring进行数据访问

    综上所述,Spring框架提供了丰富的数据访问工具和策略,无论是在传统的JDBC基础上,还是通过ORM或JPA,都能有效地进行数据库操作。理解和掌握这些知识点,将有助于提升你在开发中的效率和代码质量。

    Spring学习课件PPT

    5. **Spring数据访问策略.ppt** - 这部分可能涵盖了Spring对各种数据源的支持,包括JDBC、ORM(如Hibernate、MyBatis)以及NoSQL数据库。它会讨论Spring的事务管理,如编程式和声明式事务,并解释如何通过AOP实现...

    Spring基础:数据访问(1)

    综上所述,"Spring基础:数据访问(1)"这个主题涵盖了Spring与数据库交互的多种方式,包括基本的JDBC支持、ORM框架的集成、高级的Spring Data JPA特性,以及事务管理和测试策略。通过学习这些内容,开发者能够更好地...

    spring2跨数据源访问

    标题“spring2跨数据源访问”涉及到的是Spring框架在处理多数据源情况下的技术要点,主要涵盖如何在Spring应用中实现对多个数据库的灵活访问。在这个主题中,我们通常会讨论以下几个关键知识点: 1. **多数据源配置...

    spring多数据源

    在许多实际项目中,我们可能需要连接并操作多个数据库,比如主从数据库、读写分离、不同环境的数据隔离等,这时就需要用到Spring的多数据源支持。 Spring多数据源允许我们在一个应用中同时管理多个数据库连接,通过...

    spring资源访问

    `Resource`接口是Spring中所有资源访问策略的基础。它定义了一系列的方法来操作资源,这些方法包括: - `getInputStream()`:用于打开资源并返回一个输入流,以便于进一步处理资源内容。 - `exists()`:判断资源...

    Spring 数据源不同配置

    在Spring框架中,数据源(DataSource)的配置是应用程序与数据库交互的核心部分。Spring支持多种数据源...在实际开发中,结合使用连接池、事务管理策略以及Spring Boot的自动配置功能,可以构建高效稳定的数据访问层。

    SpringSession同时支持Cookie和header策略

    这个工具扩展了Spring框架的功能,使得在集群服务器之间共享session数据变得简单。本文将深入探讨SpringSession如何支持Cookie和header策略,并解析`CookieHeaderHttpSessionStrategy.java`这个文件中的关键概念和...

    spring资源访问的一个例子

    Spring Boot会自动配置`WebMvcAutoConfiguration`,它包含了处理静态资源的策略。默认情况下,它会从`src/main/resources/static`、`src/main/resources/public`、`src/main/resources/resources`和`src/main/webapp...

    Springcloud 多数库 多数据源整合,查询动态切换数据库

    总的来说,Spring Cloud多数据源整合和动态切换数据库是一项挑战性的工作,但通过合理的架构设计和Spring框架的特性,可以有效地实现这一功能,为大型分布式系统提供灵活和可扩展的数据访问能力。

    Spring多数据源解决方案

    如图2所示,这个选择逻辑可能会深入到业务代码中,导致数据访问API如Hibernate和iBatis等变得复杂,需要维护多个SessionFactory或SqlMapClient实例。 为了解决这个问题,Spring提供了一种基于Proxy模式的解决方案,...

    Spring Boot多数据源(支持Spring声明式事务切换和回滚).pdf

    在本文中,我们将深入探讨如何实现动态数据源切换,支持Spring声明式事务管理,并讨论多数据源回滚策略。以下是对这些知识点的详细说明: 1. **动态数据源切换**: - 通过AspectJ实现数据源的动态切换,可以设置在...

    基于Spring多数据源实例

    2. **定义数据源选择策略**:为了实现动态切换,我们需要一个策略来决定何时以及如何选择数据源。这可以通过实现Spring的AOP(面向切面编程)来完成,例如定义一个切面,该切面在特定的方法执行前检查上下文信息,...

    真正意义的spring动态切换数据源源码

    Spring框架提供了丰富的功能,包括依赖注入、AOP(面向切面编程)、MVC(模型-视图-控制器)以及数据访问层的支持。本文将深入探讨“真正意义的Spring动态切换数据源”这一主题,并结合源码进行分析。 动态数据源...

    spring整合mybatis多数据源

    在IT行业中,Spring框架与MyBatis的整合是常见的数据访问技术组合,它们可以提供灵活、高效的数据库操作。当我们需要处理多个数据源时,例如在分布式系统或读写分离的场景下,Spring整合MyBatis的多数据源切换就显得...

    SpringBoot-SpringData-多数据源

    Spring Data 是一个旨在简化数据访问层的项目,支持多种数据库,如 JPA、MongoDB、Neo4j 等。它提供了泛型 Repository 接口,使得与数据库的交互变得更加简洁。 **三、多数据源配置** 1. **配置文件** 在 Spring ...

    使用SpringAop使用Oracle数据权限控制

    在实际项目中,可能还需要考虑其他因素,如缓存策略、性能优化以及与其他安全框架(如Spring Security)的协同工作等。总的来说,Spring AOP与Oracle的数据权限控制相结合,为大型企业应用提供了强大的安全保障。

    Spring+Ibatis 访问多个数据源

    下面将详细介绍如何在Spring中配置和使用多个数据源,以及结合Ibatis进行数据访问。 首先,我们需要在`jdbc.properties`文件中配置每个数据源的相关参数,如驱动类名、URL、用户名和密码。在这个例子中,有两个数据...

Global site tag (gtag.js) - Google Analytics