重生之我在地球当程序员-Spring和MyBatis结合篇
本篇主要讲述Spring整合MyBatis,以及常见的一些操作
整合思路
Spring是一个一站式框架,支撑整合多个框架,Mybatis是一个持久层框架,所以我们需要将Mybatis
往Spring上整合。当然Spring自带了一个持久层框架JdbcTemplate,现阶段流行的Mybatis框
架,以及之前比较流行的Hibernate。当然市面上持久层框架有很多,就不一一列举。
三种持久层框架区别:
JdbcTemplate, Mybatis, 和 Hibernate 都是Java中用于操作数据库的工具,但它们的实现方式和设计目标略有不同。
JdbcTemplate 是 Spring 框架中的一个组件,它提供了一个简单的 API 用于执行 SQL 语句和查询。JdbcTemplate 可以在不涉及复杂对象的情况下执行 CRUD 操作,它不提供任何对象关系映射(ORM)功能。它的主要优点是简单易用,因为它非常轻量级,不需要额外的配置,而且对性能要求较高的场景也比较适用。
Mybatis 是一个独立于任何框架之外的 ORM 模块,它提供了比 JdbcTemplate 更丰富的功能。Mybatis 使用 XML 或注解来映射数据库表和字段,它支持复杂的查询和数据转换。Mybatis 的主要优点是高度可配置和可扩展,可以很方便地与其他框架集成,同时它也提供了较好的性能。
Hibernate 是另一个 ORM 模块,它也提供了丰富的功能,可以简化数据库操作。Hibernate 使用 Java 面向对象的方式对数据库进行建模,它支持自动的 CRUD 操作和查询优化。Hibernate 的主要优点是易用性和高度的可扩展性,它可以很方便地与其他 Java 应用程序集成,同时提供了较好的性能和可维护性。
总的来说,选择哪种工具取决于应用场景和需求。如果需要快速执行 SQL 语句和查询,可以选择 JdbcTemplate;如果需要丰富的 ORM 功能和高度的可扩展性,可以选择 Mybatis 或 Hibernate。
整合
- 导入依赖
<properties>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<!--导入junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--导入spring的context坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!--导入Jdbc模块依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--导入Mysql 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--导入C3P0连接池或者druid数据库连接池二选一-->
<!--导入C3P0连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.11</version>
</dependency>
<!--aop-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!--mybatis-Spring适配包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.0</version>
</dependency>
<!-- mybatis orm框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
</dependencies>
- 配置IOC以c3p0为例
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启包扫描-->
<context:component-scan base-package="com.test"> </context:component-scan>
<!-- 配置数据源第一个是c3p0配置第二个是Druid -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--连接数据库的必备信息-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc.url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--Mybatis 核心对象: 工厂对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--工厂创建必须注入一个数据源-->
<property name="dataSource" ref="dataSource"/>
<!--指定mapper文件位置-->
<property name="mapperLocations" value="classpath:com/test/mapper/*Mapper.xml"></property>
<!--引入Mybatis的核心配置文件:
如果Mybaits的核心配置要保留,需要再此处配置:
-->
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
<!--别名配置-->
<property name="typeAliasesPackage" value="com/test/pojo"/>
<!--进行分页插件的配置-->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<value>
helperDialect=MySQL
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<!--配置接口的扫描-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定了包: 能够将包下的接口生成实现类: -->
<property name="basePackage" value="com.test.mapper"></property>
</bean>
<!--配置平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
构建数据库表并创建实体User
create table User(
id int primary key auto_increment,
name varchar(32) not null,
address varchar(32) not null,
birthday date
);
public class User implements Serializable {
private Integer id;
private String name;
private String address;
private Date birthday;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", address='" + address + '\'' +
", birthday=" + birthday +
'}';
}
}
18.4 编写dao层的接口UserMapper
public interface UserMapper {
int insert(User user);
int update(User user);
int delete(Integer id);
User findById(Integer id);
List<User> findAll();
}
构建mapper接口对应的sql配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.offcn.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.offcn.pojo.User">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="address" jdbcType="VARCHAR" property="address" />
<result column="birthday" jdbcType="DATE" property="birthday" />
</resultMap>
<insert id="insert" parameterType="com.offcn.pojo.User">
insert into user (name, birthday, address)
values (#{name}, #{birthday},#{address})
</insert>
<update id="update">
update user
set
name= #{name},
birthday=#{birthday},
address = #{address}
where id=#{id}
</update>
<delete id="delete">
delete from user
where id =#{id}
</delete>
<select id="findById" resultMap="BaseResultMap">
select * from user where id=#{id}
</select>
<select id="findAll" resultMap="BaseResultMap">
select * from user
</select>
</mapper>
构建服务层接口UserService
public interface UserService {
int insert(User user);
int update(User user);
int delete(Integer id);
User findById(Integer id);
List<User> findAll();
}
18.7 构建服务层实现类UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public int insert(User user) {
int num = userMapper.insert(user);
return num;
}
@Override
public int update(User user) {
int num = userMapper.update(user);
return num;
}
@Override
public int delete(Integer id) {
int num = userMapper.delete(id);
return num;
}
@Override
public User findById(Integer id) {
User user = userMapper.findById(id);
return user;
}
@Override
public List<User> findAll() {
List<User> userList = userMapper.findAll();
return userList;
}
}
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestAccountTransfer {
@Autowired
private UserService userService;
//save
@Test
public void testInsert(){
User user = new User();
user.setName("admin");
user.setAddress("china");
user.setBirthday(new Date());
int num = userService.insert(user);
System.out.println("num:"+num);
}
//update
@Test
public void testUpdate(){
User user = new User();
user.setName("marry");
user.setAddress("America");
user.setBirthday(new Date());
user.setId(1);
int num = userService.update(user);
System.out.println("num:"+num);
}
//delete:
@Test
public void testDelete(){
int num = userService.delete(1);
System.out.println("num:"+num);
}
//findById
@Test
public void testFindById(){
User user = userService.findById(2);
System.out.println("user:"+user);
}
//findAll
@Test
public void testFindByAll(){
List<User> userList = userService.findAll();
System.out.println("userList:"+userList);
}
}
两个数据库连接池的区别:
Druid和C3P0都是常用的数据库连接池工具,它们的作用是在Java应用程序中管理和优化数据库连接。它们之间的区别主要在于实现和使用方式上。
Druid是一个实现了简易数据库连接池的类,它使用一个线程安全的队列来管理连接。Druid的配置参数相对较少,常用的配置参数包括:
url:数据库连接URL,例如jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
username:数据库用户名
password:数据库密码
maxActive:连接池中最多可以同时存在的连接数,建议根据系统的实际需求进行配置
minIdle:连接池中最小的空闲连接数,建议根据系统的实际需求进行配置
initialSize:连接池中初始的连接数,建议根据系统的实际需求进行配置
testWhileIdle:是否在空闲时测试连接,以确保其可用性
testOnBorrow:是否在每次获取连接时都进行测试
testOnReturn:是否在每次归还连接时都进行测试
C3P0是一个开源的数据库连接池工具,它提供了更加灵活和可配置的连接池管理功能。C3P0的配置参数相对较多,常用的配置参数包括:
url:数据库连接URL,例如jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
user:数据库用户名
password:数据库密码
maxPoolSize:连接池中最多可以同时存在的连接数,建议根据系统的实际需求进行配置
minPoolSize:连接池中最小的连接数,建议根据系统的实际需求进行配置
initialPoolSize:连接池中初始的连接数,建议根据系统的实际需求进行配置
maxIdleTime:连接在池中最大空闲时间,超过这个时间后将被回收
numHelperThreads:连接池中用于处理并发请求的线程数,建议根据系统的实际需求进行配置
testConnectionOnCheckin:是否在连接入库前测试连接,以确保其可用性
testConnectionOnCheckout:是否在连接出库时测试连接
总的来说,Druid的配置参数相对较少,使用起来更加简单,而C3P0的配置参数相对较多,提供了更多的可定制化选项。在实际使用过程中,可以根据实际需求和应用场景来选择使用Druid或C3P0。