Spring数据访问策略
Spring封装的数据访问异常
与SQLException是一个Checked Exception不同,Spring定义的基本书籍访问异常DataAccessException是一个RuntimeException,DataAccessException继承自NestedRuntimeException,完整的保留了原始异常信息。
// 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" 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" 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" 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" 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 /></entry><entry key="pre-insert"><bean /></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" 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" ref="dataSource"/><!-- Adapter 选择实现JPA的具体框架 --><property name="jpaVendorAdapter"><bean value="true" /><property name="generateDdl" value="false" /></bean></property></bean> <bean id="jpaTxManager" 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); }}