- DAO皆为接口,面向接口编程
- DAO无关持久化技术
- Spring提供统一的数据访问异常体系,Spring提供的异常为非检查型异常,允许不捕获
- Spring将数据访问的相同部分抽象为模板,数据操作抽象为回调;前者包括连接管理、事务管理、资源管理和错误处理
- 模板例如JdbcTemplate
<!-- 在tomcat的server.xml中加入下面的配置,或在META-INF目录下面新建context.xml再加入下面的配置 --> <?xml version="1.0" encoding="UTF-8"?> <Context> <Resource name="jdbc/demoDb" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/demo" username="root" password="123" maxActive="50" maxIdle="30" maxWait="10000"/> </Context> <!-- 创建数据源,方法1 --> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>java:comp/env/jdbc/demoDb</value> </property> </bean> <!-- 创建数据源,方法2 --> <beans> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/demoDb"/> </beans>
// JavaConfig方式 @Bean public JndiObjectFactoryBean dataSource() { JndiObjectFactoryBean jndiObjectFB = new JndiObjectFactoryBean(); jndiObjectFB.setJndiName("jdbc/demoDb"); jndiObjectFB.setResourceRef(true); jndiObjectFB.setProxyInterface(javax.sql.DataSource.class); return jndiObjectFB; }
[参考]
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> <!-- 其他配置 ... --> </bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="com.mysql.jdbc.Driver" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
包括JdbcTemplate、NamedParameterJdbcTemplate,还有一个从Spring 3.1开始已经过时的SimpleJdbcTemplate
// 定义一个JdbcTemplate @Bean public NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource) { return new NamedParameterJdbcTemplate(dataSource); } // 定义一个Repository @Repository public class UserRepository { private static final String sql = "select id, username from users where id=:id"; @Resource("jdbcTemplate") NamedParameterJdbcTemplate jdbcTemplate; // 也可以使用JdbcOperations,JdbcTemplate实现了该接口,这样可以减少耦合 public User findUser(int id) { Map params = new HashMap(); params.put("id", id); return jdbcOperations.queryForObject( sql, new UserRowMapper(), params ); } private static final class UserRowMapper implements RowMapper<Spitter> { public User mapRow(ResultSet rs, int rowNum) throws SQLException { return new User( rs.getLong("id"), rs.getString("username")); } } } // 运用Java8 lamdas改写上面的代码 public User findUser(int id) { // params ... return jdbcOperations.queryForObject( "sql语句", (rs, rowNum) -> { return new User( rs.getLong("id"), rs.getString("username")); }, params ); }
- ORM可以提供延迟加载、预先抓取、级联、缓存、分布式缓存、生成SQL等功能
- Spring集成ORM,可以提供声明式事务、异常处理、资源管理等功能
HibernaateTemplate会造成repository和Spring的耦合,现在推荐在repository里面注入HibernateSessionFactory,以此获得session
@Repository public class UserDaoImpl implements UserDao { HibernaateTemplate hibernaateTemplate; public void setSessionFactory(SessionFactory sessionFactory) { this.hibernaateTemplate = new HibernaateTemplate(essionFactory); } public User findOne(int id) { return (User)this.hibernaateTemplate.get(User.class, id); } }
- Hibernate Session可以实现数据库数据的增删改查等功能
- Hibernate Session Factory可以开关并管理session
- Spring提供了org.springframework.orm.hibernate4.LocalSessionFactoryBean以获得Hibernate 4的session factory,与更早的版本不同,该版本可以同时支持xml和注解配置的Hibernate映射
// JavaConfig @Bean public LocalSessionFactoryBean sessionFactory(DataSource dataSource) { LocalSessionFactoryBean factory = new LocalSessionFactoryBean(); factory.setDataSource(dataSource); // 支持xml配置的Hibernate映射 factory.setMappingSource(new String[] {"User.hbm.xml"}); // 支持注解配置的Hibernate映射 // factory.setPackagesToScan(new String[] {"x.y.z.domain"}); Properties props = new Properties(); props.setProperty("dialect", "org.hibernate.dialect.MySQL5InnoDBDialect"); factory.setHibernateProperties(props); return factory; } // 让平台相关的异常自动转换成Spring统一的非检查型异常,需结合@Repository注解 @Bean public BeanPostProcessor persistenceTranslation() { return new PersistenceExceptionTranslationPostProcessor(); } // DAO @Repository public class UserDaoImpl implements UserDao { @Autowired SessionFactory sessionFactory; public User findOne(int id) { return (User)sessionFactory.getCurrentSession().get(User.class, id); } public User findByUsername(String username) { return (User) sessionFactory.getCurrentSession() .createCriteria(User.class) .add(Restrictions.eq("username", username)) .list().get(0); } }
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>x/y/z/domain/petclinic.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=${hibernate.dialect} </value> </property> </bean> <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
- JPA是Java EE 5的标准ORM接口,也是ejb3规范的一部分
- JPA是规范,要使用JPA,需要借助其实现,例如Hibernate、EclipseLink、TopLink、OpenJpa等
- Hibernate的核心之一是Session,JPA相对应的核心是Entity Manager
- Spring集成JPA的好处[参考]
|