MyBatis整合Spring
目的:
是为了能在业务逻辑层service调用数据访问层dao中的方法
步骤:
- 配置数据库连接池
- 配置SqlSessionFactory工厂
- 配置dao所在的包
- 将dao中的接口将自动注册到Spring的ioc容器中
- dao的对象进行依赖注入
下面是具体的实现步骤:
第一步:配置数据库连接池
<!-- 配置文件db.properties存储数据库连接的信息 -->
jdbc.url=jdbc:mysql:///java2005?serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root
jdbc.driver=com.mysql.jdbc.Driver
<!-- 配置文件db.properties的位置在类文件目录下-->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置druid数据库连接池对象-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="password" value="${jdbc.password}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
</bean>
第二步:配置SqlSessionFactory工厂
<!-- 配置SqlSession工厂-->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 配置分页插件pagehelper 为了将数据里面的数据进行分页处理-->
<property name="plugins">
<set>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<!-- 数据库方言,可选择:oracle,mysql,mariadb 等-->
<prop key="helperDialect">mysql</prop>
<!--reasonable:分页合理化参数,默认值:false。
当该参数设置为true时,pageNum<=0时会查询第一页,
pageNum>pages(超过总数时),会查询最后一页-->
<prop key="reasonable">true</prop>
<!--supportMethodsArguments:
是否支持通过 Mapper 接口参数来传递分页参数,默认值:false-->
<prop key="supportMethodsArguments">true</prop>
</props>
</property>
</bean>
</set>
</property>
</bean>
第三步:配置dao所在的包
<!-- 配置要扫描的dao包-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.li.dao"/>
</bean>
在这里补充个知识点MapperScannerConfigurer,想要了解该类的作用,就得先了解MapperFactoryBean
比如下面这个官方文档中的配置:
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
org.mybatis.spring.sample.mapper.UserMapper是一个接口,我们创建一个MapperFactoryBean实例,然后注入这个接口和sqlSessionFactory(mybatis中提供的SqlSessionFactory接口,MapperFactoryBean会使用SqlSessionFactory创建SqlSession这两个属性。
之后想使用这个UserMapper接口的话,直接通过spring注入这个bean,然后就可以直接使用了,spring内部会创建一个这个接口的动态代理。
当发现要使用多个MapperFactoryBean的时候,一个一个定义肯定非常麻烦,于是mybatis-spring提供了MapperScannerConfigurer这个类,它将会查找类路径下的映射器并自动将它们创建成MapperFactoryBean。
这段配置会扫描com.li.dao下的所有接口,然后创建各自接口的动态代理类
当这里的动态代理类生成时我们才可以对service中创建的xxxDao对象进行注入操作,因为dao中存在的都是接口无法被实例化。
第四步:将dao中的接口将自动注册到Spring的ioc容器中
IOC(Inversion of Control,控制反转)。这是spring的核心,贯穿始终。所谓IOC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。
这里在类上添加@Repository注解实现
@Repository
public interface HouseDao {
// List<House> findAll(@Param("proname") String proname,@Param("username") String username,@Param("uid") String uid);
List<House> findAll( String proname, String username,String uid);
}
Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller。
在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层相对应。
虽然目前这3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。
所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用上述注解对分层中的类进行注释。
@Service用于标注业务层组件 服务
@Controller用于标注控制层组件
@Repository用于标注数据访问组件,即DAO组件
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注
第五步:dao的对象进行依赖注入
这里在类上添加 @Autowired注解实现
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public boolean login(User user) {
User login = userDao.login(user);
return login != null;
}
}
@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。
说起按名称装配:我们还可以说说Spring的ioc容器:Map结构
当我们在dao上的接口添加
@Repository
public interface HouseDao
这里ioc的map结构默认的 key(String类型) 就是 houseDao(接口名首字母小写)
map结构的value(Object类型) 就是他的实现类,所以这里的value就是MapperScannerConfigurer进行了动态代理生成的代理类,然后ioc容器生成的那个对象。
这里默认的情况也就是注入那个实现类的对象,而当有MapperScannerConfigurer进行了动态代理生成的多个代理类,然后ioc容器生成的多个对象时。@Autowired注解会根据private UserDao userDao中的变量名进行注入,我们可以在@Repository注解中添加(value=“userDao”),然后就可以对private UserDao userDao中的userDao进行注入了。
而当按名注入没有对应的名字时:可以采用
@Autowired
@Qualifier("userDao")
private UserDao userDao
对其进行注入
而这的效果和
@Resource(name = "userDao")
private UserDao userDao
是一样的
说的简单点就是:
他们的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的
Autowired:
作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
如果Ioc容器中有多个类型匹配时:
出现位置:
可以是变量上,也可以是方法上
细节:
在使用注解注入时,set方法就不是必须的了。
Qualifier:
作用:在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以(稍后我们讲)
属性:
value:用于指定注入bean的id。
Resource
作用:直接按照bean的id注入。它可以独立使用
属性:
name:用于指定bean的id。
以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。
另外,集合类型的注入只能通过XML来实现。
Value
作用:用于注入基本类型和String类型的数据
属性:
value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式)
SpEL的写法:${表达式}