在学习日记二中,我们springbot+mybatis实现是通过mapper接口,mapper.xml。每一个的mapper.xml都对应一个mapper接口,我们的service调用的时候也是调用对应的mapper接口然后去操作数据库。所以当数据库的表多的情况或者sql语句复杂的情况下,为了项目的维护方便。以及不必需要那么多的mapper接口。
所以我们可以通过传统的SqlSessionTemplate来实现一个通用的Dao对mapper.xml直接操作。直接不需要mapper接口层。不通过mapper接口层来执行对应sql。直接使用通用的Dao来调用。
既然不需要mapper接口了。所以我们把SpringBootDemoApplication项目启动类扫描mapper接口的@MapperScan注释掉,如果没有再启动类里面写@MapperScan而是单独写@Mapper,请把@Mapper注释掉。
package com.lds.springbootdemo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication
/*直接在Mapper类上面添加注解@Mapper,这种方式要求每一个mapper类都需要添加此注解,麻烦
所以可以通过使用@MapperScan可以指定要扫描的Mapper类的包的路径
*/
//注释掉
//@MapperScan("com.lds.springbootdemo.mapper")
// 用来指定配置文件的位置
@PropertySource(value={"classpath:dbconfig.properties"})
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
此时我们就可以删除mapper接口了。删不删都行,反正现在注释掉了@MapperScan或者@Mapper。
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '***': Unsatisfied dependency expressed through field '***';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '***': Unsatisfied dependency expressed through field '***';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '***': Unsatisfied dependency expressed through field 'sqlSessionTemplate';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sqlSessionTemplate' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'sqlSessionTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource: 'file ***'; nested exception is java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.lds.repastsystem.mapper.employeeMapper.selectByAccount. please check file [***] and ***Mapper.java (best guess)
解决办法:
然后我们application.properties项目配置文件中的mybatis的mapper映射路径必须要写
#设置项目访问名称
server.servlet.context-path=/springBootDemo
#mysql数据源配置
spring.datasource.driver-class-name=${driverClass}
spring.datasource.url=${url}
spring.datasource.username=${user}
spring.datasource.password=${password}
#mybatis的mapper映射路径
mybatis.mapperLocations=classpath:mybatis/mapper/*.xml
之后的操作就是进行编写Dao。
在com.lds.repastsystem包下新建一个dao包。然后编写Dao的接口的实现类。
Dao.java
package com.lds.springbootdemo.dao;
/**
* @program: springbootdemo
* @description:
* @author:
* @createData:
* @updateAuthor:
* @updateData:
* @updateContent:
* @Version: 1.0
* @email: [email protected]
* @blog: www.b0c0.com
*/
public interface Dao {
/**
* 保存对象
* @param str
* @param obj
* @return
* @throws Exception
*/
public Object save(String str, Object obj) throws Exception;
/**
* 修改对象
* @param str
* @param obj
* @return
* @throws Exception
*/
public Object update(String str, Object obj) throws Exception;
/**
* 删除对象
* @param str
* @param obj
* @return
* @throws Exception
*/
public Object delete(String str, Object obj) throws Exception;
/**
* 查找返回一个对象
* @param str
* @param obj
* @return
* @throws Exception
*/
public Object selectForOne(String str, Object obj) throws Exception;
/**
* 查找返回多个对象
* @param str
* @param obj
* @return
* @throws Exception
*/
public Object selectForList(String str, Object obj) throws Exception;
}
DaoSupport.java
package com.lds.springbootdemo.dao;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @program: springbootdemo
* @description:
* @author:
* @createData:
* @updateAuthor:
* @updateData:
* @updateContent:
* @Version: 1.0
* @email: [email protected]
* @blog: www.b0c0.com
*/
/*
注解了@Repository的类上如果数据库操作中抛出了异常,就能对其进行处理,
转而抛出的是翻译后的spring专属数据库异常,方便我们对异常进行排查处理)。
*/
@Repository
/*
加入 @Transactional 注解,使用默认配置,抛出异常之后,事务会自动回滚,数据不会插入到数据库。
*/
@Transactional
public class DaoSupport implements Dao {
/**
* @Autowired默认按类型装配(这个注解是属于spring的),
* 默认情况下必须要求依赖对象必须存在,如果要允许null值,
* 可以设置它的required属性为false,如:@Autowired(required=false) ,
* 如果我们想使用名称装配可以结合@Qualifier注解进行使用 @Autowired()@Qualifier("baseDao")
* @Resource(这个注解属于J2EE的),默认按照名称进行装配,名称可以通过name属性进行指定,
* 如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,
* 如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。
* 但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
*/
@Autowired
private SqlSessionTemplate sqlSessionTemplate;
/**
* 保存对象
* @param str
* @param obj
* @return
* @throws Exception
*/
public Object save(String str, Object obj) throws Exception {
return sqlSessionTemplate.insert(str, obj);
}
/**
* 批量更新
* @param str
* @param objs
* @return
* @throws Exception
*/
public Object batchSave(String str, List objs)throws Exception{
return sqlSessionTemplate.insert(str, objs);
}
/**
* 修改对象
* @param str
* @param obj
* @return
* @throws Exception
*/
public Object update(String str, Object obj) throws Exception {
return sqlSessionTemplate.update(str, obj);
}
/**
* 批量更新
* @param str
* @param objs
* @return
* @throws Exception
*/
public void batchUpdate(String str, List objs)throws Exception{
SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
//批量执行器
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false);
try{
if(objs!=null){
for(int i=0,size=objs.size();i
里面有两个参数,第一个参数就直接填希望去执行mapper.xml中的sql。第二个就是我们需要sql中需要传递的参数。就好比登录验证实例来说:
sbd_userMapper.xml
*****省略部分内容*****
*****省略部分内容*****
mapper标签的namespace属性的值:com.lds.springbootdemo.mapper.sbd_userMapper
执行的sqlId的值:selectByAccount
我们的第一个参数就是:
com.lds.springbootdemo.mapper.sbd_userMapper.selectByAccount
之后让我找很长时间的原因,最后一步一步debug进入源码调试看到才发现必须要和namespace属性的值一致。不能省略前面的内容。
解决办法:
然后就是lognService去通过调用通用Dao。
LoginServiceImpl.java
package com.lds.springbootdemo.service.login_register;
import com.lds.springbootdemo.dao.DaoSupport;
import com.lds.springbootdemo.domain.sbd_user;
import com.lds.springbootdemo.mapper.sbd_userMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @program: springbootdemo
* @description:
* @author:
* @createData:
* @updateAuthor:
* @updateData:
* @updateContent:
* @Version: 1.0
* @email: [email protected]
* @blog: www.b0c0.com
*/
@Service
public class LoginServiceImpl implements LoginService {
//@Autowired
//private sbd_userMapper userMapper;
@Autowired
private DaoSupport dao;
/**
* 登录验证Service
* @return
*/
@Override
public boolean loginValidate(String account,String password) {
boolean retu=false;
//sbd_user em=userMapper.selectByAccount(account);
sbd_user user= null;
try {
user = (sbd_user) dao.selectForOne("sbd_userMapper.selectByAccount",account);
} catch (Exception e) {
e.printStackTrace();
}
if(user!=null&&password.equals(user.getPassword())){
retu=true;
}
return retu;
}
}
然后就可以实现了,这样的话不管以后有多少模块功能,只要和数据库的操作直接调用这个通用Dao就行,不必再写很多的Mapper.java接口文件。