Spring 不強制綁定特定 ORM,但提供一致性抽象層,讓你在保留各框架特性的同時,獲得:
DataAccessException 體系(RuntimeException)@Transactional 橫跨 JDBC、Hibernate、JPA、MyBatis,支援 JTA 分散式事務<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/mydb"/>
<property name="username" value="app"/>
<property name="password" value="secret"/>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.myapp.domain"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- JPA EntityManagerFactory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.myapp.domain"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true"/>
</bean>
</property>
</bean>
<!-- MyBatis SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:mapper/**/*.xml"/>
</bean>
@Repository
public class HibernateUserDao implements UserDao {
private final SessionFactory sessionFactory;
@Autowired
public HibernateUserDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public User findById(Long id) {
return sessionFactory.getCurrentSession().get(User.class, id);
}
}
@Repository
public class MyBatisUserDao implements UserDao {
private final SqlSessionTemplate sqlSession;
@Autowired
public MyBatisUserDao(SqlSessionFactory sqlSessionFactory) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
@Override
public User findById(Long id) {
return sqlSession.selectOne("com.myapp.mapper.UserMapper.selectById", id);
}
}
HibernateTemplate / JpaTemplate:封裝 Session/EntityManager 獲取、關閉、異常轉換SqlSessionTemplate:線程安全、自動參與 Spring 事務Spring PersistenceExceptionTranslator 攔截底層異常,映射為 org.springframework.dao.DataAccessException 子類:
| 底層異常 | Spring 異常 | 語義 |
|---|---|---|
| ConstraintViolationException | DataIntegrityViolationException | 唯一鍵/外鍵/非空約束違反 |
| OptimisticLockException | ObjectOptimisticLockingFailureException | 樂觀鎖衝突 |
| QueryTimeoutException | QueryTimeoutException | 查詢超時 |
| DeadlockLoserDataAccessException | DeadlockLoserDataAccessException | 死鎖受害者 |