Mybatis va Spring
Bài đăng này đã không được cập nhật trong 6 năm
MyBatis là một persistence framework mã nguồn mở, đơn giản, gọn nhẹ và dễ sử dụng. Trước đây MyBatis được gọi là iBatis và được viết ra năm 2002 bởi Clinton Begin. Mybatis 3 được thiết kế lại từ iBatis, có hỗ trợ Mapper và Annotations. Sự khác nhau lớn nhất giữa Mybatis và các persistence framework khác đó là Mybatis nhấn mạnh việc sử dụng SQL, trong khi các framework khác như Hibernate sử dụng một ngôn ngữ truy vấn tùy chỉnh.
Sau đây sẽ là một ví dụ về việc sử dụng Mybatis trong một project Spring, với mybatis-spring
Data Source
Bất kì Data Source nào đều được chấp nhận, ví dụ như org.springframework.jdbc.jar
:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
Cài đặt SqlSessionFactory
Với XML:
# SqlSessionFactoryBuilder
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" /> <!-- Obliged -->
<!-- Indicate location of mapper files where exists mysql statements -->
<property name="mapperLocations" value="classpath*:/mybatis/*Mapper.xml"/>
<!-- Indicate mybatis config files where exists typeAliases, settings, etc -->
<property name="configLocation" value="classpath:/mybatis/mybatis-config.xml"/>
</bean>
Với Anotation:
# SqlSessionFactoryBean
String resource = "path/to/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
Định nghĩa mappers
Có 2 cách để khai báo mappers:
- Annotation based
- XML based
Khi định nghĩa dựa trên XML:
- Báo với
SqlSessionFactoryBean
nơi để tìm được nó bởimapperLocations
- Mapper namespace cần phải đặt đường dẫn đầy đủ đối với mapper interface.
- id phải cùng tên với phương thức trong mapper namespace, tương tự cả với tham số, kiểu trả về, ...
Ví dụ dưới đây bao gồm cả XML và anotation
<mapper namespace="com.dong.web.mapper.UserMapper">
<select id="getRowCount" resultType="int">
select count(*) from tb_user
</select>
</mapper>
public interface UserMapper {
int getRowCount();
@Select("select * from tb_user")
List<User> getAllUsers();
}
SqlSession
Với Mybatis cơ bản:
SqlSession session = sqlSessionFactory.openSession();
try {
...
session.commit();
} catch(Exception e) {
e.printStackTrace();
session.rollback();
} finally {
session.close();
}
Nhưng với mybatis-spring
, bean sẽ được inject với một safe thread SqlSession
, cho phép tự động commit, rollbacks và close session dựa trên Spring’s transaction configuration.
Chúng ta có 2 cách để lấy session trong DAOs:
- SqlSessionTemplate
- SqlSessionDaoSupport Nhưng tôi thích sử dụng MapperScannerConfigurer hoặc MapperFactoryBean trực tiếp để tránh mã hoá DAO bằng tay. MapperScannerConfigurer thậm chí có thể tự động quét mapper interfaces. Đó là sự lựa chọn rất tốt!
Transaction
Đầu tiên, trong mybatis-spring
, bạn cần bật Spring transaction processing:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
Sau đó thêm @Transactional annotation vào tầng services.
SqlSessionTemplate
SqlSessionTemplate
implements SqlSession
, nó là một thread an toàn và có thể được chia sẻ bởi nhiều DAOs hoặc mappers. Nó được sử dụng để:
- Chắc chắn rằng
SqlSession
đang được sử dụng là một liên kết với Spring transaction hiện tại khi gọi truy vấn SQL. - Quản lý session life-cycle, bao gồm closing, committing hoặc rolling back session nếu cần
- Dịch MyBatis exceptions thành Spring DataAccessExceptions.
Vì vậy, ý tưởng ở đây là tạo bean cho SqlSessionTemplate
và inject nó vào tầng DAO.
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<!-- Inject it in DAO layer -->
<bean id="userDAO" class="com.dong.web.dao.UserDaoImpl">
<property name="sqlSession" ref="sqlSession" />
</bean>
DAO class với injected sqlSession:
public class UserDaoImpl implements UserDao {
private SqlSession sqlSession;
public void setSqlSession(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> getAllUsers() {
return sqlSession.select("com.dong.web.mapper.UserMapper.getAllUsers");
}
}
Batch Processing
Để bật tính năng batch:
<bean id="sqlSession" class="com.dong.web.dao.UserServiceImpl">
<constructor-arg index="0" ref="sqlSessionFactory" />
<constructor-arg index="1" value="BATCH" />
</bean>
Bây giờ tất cả các câu lệnh SQL đều sẽ được batched:
public void insertUsers(User[] users) {
for (User user : users) {
sqlSession.insert("org.dong.web.mapper.UserMapper.insertUser", user);
}
}
SqlSessionDaoSupport
Đây là một lớp trừu tượng hỗ trợ SqlSession
. Chúng ta có thể gọi getSqlSession()
bằng cách kế thừa SqlSessionDaoSupport
để lấy SqlSession
:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return (User) getSqlSession().selectOne("com.dong.web.mapper.UserMapper.getUser", userId);
}
}
MapperFactoryBean
Nó được sử dụng để tránh mã hóa các DAO bằng tay bởi SqlSessionDaoSupport hoặc SqlSessionTemplate, do đó không có DAO ở đây trong mã java! Nó xử lý tạo một SqlSession cũng như đóng nó. Nếu có Spring transaction đang diễn ra, session cũng sẽ được committed hoặc rolled back khi transaction hoàn tất.
<!-- Create a MapperFactoryBean for UserMapper interface -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.dong.web.mapper.UserMapper" />
</bean>
<!-- Inject mapper in service layer -->
<bean id="userService" class="com.dong.web.service.UserServiceImpl">
<property name="userMapper" ref="userMapper" />
</bean>
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
public List<User> getAllUsers() {
return this.userMapper.getAllUsers();
}
}
MapperScannerConfigurer
Với MapperFactoryBean
, chúng ta cần khai báo một bean cho mỗi mapper interface. Do đó cách tốt hơn là dùng MapperScannerConfigurer
để tự động quét và tìm kiếm mapper interfaces và khai báo chúng như là MapperFactoryBean
.
<!-- Scan all the interfaces under mapper/ -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dong.web.mapper" />
</bean>
Chú ý: IDE sẽ đề cập đến Không thể autowired, bởi vì mỗi MapperFactoryBean được tạo ra bởi MapperScannerConfigurer, IDE không thể tìm ra một thực thể hiện tại.
All rights reserved