dao接口方式:
spring与mybatis中配置关键代码部分:
<!-- 动态代理实现 DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--需要扫描的dao层-->
<property name="basePackage" value="com.shadow.*.dao" />
<!--引入上面的sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!--创建SqlSessionFactory,同时指定数据源 这里使用的并不是SqlSessionFactoryBuilder,而是使用的Mybatis-spring整
合jar中的org.mybatis.spring.SqlSessionFactoryBean,并且通过configLocation配置Mybatis的配置文件-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--将数据源引入进来-->
<property name="dataSource" ref="dataSource" />
<!--mybaits的配置文件-->
<property name="configLocation" value="classpath:config/mybatis/mybatis-config.xml" />
<!--自动扫描mapper文件,实体的映射文件位置-->
<property name="mapperLocations" value="classpath:cn/shadow/mapper/*.xml" />
<!-- 自动扫描需要定义类别名的包,将包内的JAVA类的类名作为类别名
可以不配 该别名的作用就是在之后mybatis中要用到该类的时候,可以省略之前 包名+类名 的方式,直接用 类名即可-->
<!--<property name="typeAliasesPackage" value="com.shadow.*.model" />-->
</bean>
项目结构:
页面前台点击:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<form action="<%=basePath%>test/testDao2.do" method="post">
<input type="submit" value="提交testDao2"/>
</form>
</body>
</html>
跳转的页面:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>测试</title>
</head>
<body>
测试页面
后台传过来的数据 + ============================${id}
</body>
</html>
model:
public class TestModel {
int id ;
String sex;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
controller层:
@Controller
@RequestMapping("test")
public class TestController {
@Resource、@Autowired两种注入方式都可以 注入dao接口实现类实例
@Autowired
private TestService2 testService2;
/**
* dao接口方式,只是验证上面的代码是否正确(上面可以用,modelAndView可以是传过来的,且返回字符串同样可以进入到页面,不过不能传值过去)
*/
@RequestMapping(value = "testDao2.do", method = RequestMethod.POST)
public ModelAndView testDao3(HttpServletRequest request, HttpServletResponse response){
System.out.println("已经进入到testDao2");
ModelAndView modelAndView = new ModelAndView();
int math = (int)(6 + Math.random()*10);
TestModel testModel = new TestModel();
testModel.setId(math);
testModel.setSex("女");
testModel.setName(math + "name");
testService2.addTest2(testModel);
//使用modelAndView里面添加参数
modelAndView.addObject("id", testModel.getId());
modelAndView.setViewName("test");
return modelAndView;
}
service层:
public interface TestService2 {
/**
* 添加测试
* @param testModel
*/
public void addTest2(TestModel testModel);
}
service实现:
@Service
public class Test2ServiceImpl implements TestService2 {
@Autowired
private TestDao2 testDao2;
/**
* 该接口名中的方法应该和mapper中的id一样。
* @param testModel
*/
@Override
public void addTest2(TestModel testModel) {
testDao2.addTest2(testModel);
}
}
dao层:
public interface TestDao2 {
/**
* 自动实现方式
* @param testModel
*/
public void addTest2(TestModel testModel);
}
如上:注意dao层应该是接口,而且该方法应该和mapper中的id一样
<?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文件名称空间这里需要定位到dao接口位置,否则会报错
namespace的值就是dao接口的完整路劲 不然要运行的时候要报错 “is not known to the MapperRegistry”-->
<mapper namespace="com.shadow.test.dao.TestDao2">
<!--这个id就是接口里面类的方法名,这里的id必须和UserMapper接口中的接口方法名相同,不然运行的时候也要报错-->
<insert id="addTest2" parameterType="com.shadow.test.model.TestModel" useGeneratedKeys="false">
<!-- 这里sql结尾不能加分号,否则报“ORA-00911”的错误 -->
<![CDATA[
insert into
test(id, sex, name)
values
(#{id,jdbcType=INTEGER}, #{sex, jdbcType=VARCHAR}, #{name, jdbcType=VARCHAR})
]]>
</insert>
</mapper>
dao层接口方式的关键在,mapper文件要在配置中被扫描到,mapper文件中的名称空间应该是正好指向dao层的的接口文件,而接口文件中的方法和mapper问中的id要一致
第二种方式:dao层实现的方式
其实配置差不多,但多了写配置,比如mybatis和spring结合的地方的配置
<!--这里的实例就是mybatis如果要用dao实现方式必须用到的bean-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--通过构造函数注入-->
<constructor-arg index="0">
<!--引入sqlSessionFactory-->
<ref bean="sqlSessionFactory" />
</constructor-arg>
</bean>
如果没有上面的就无法获取到sqlSession
然后之前的mapper文件这里名称空间可以随便写了,但是一般还是写成cn.shadow.mapper.TestMapper这种,定位到mapper文件的位置
<!--这个namespace + 下面的id 就是一个完整的路径,在dao层我们写了完整的路径之后mybatis就是映射这个文件中的相关sql语句
这里的映射文件的namespace +id 是自定义的而不是dao 层接口的全类名+id-->
<!--<mapper namespace="cn.shadow.mapper.TestMapper">-->
<mapper namespace="TestMapper">
<insert id="addTest" parameterType="com.shadow.test.model.TestModel" >
<![CDATA[
insert into
test(id, sex, name)
values
(#{id,jdbcType=INTEGER}, #{sex, jdbcType=VARCHAR}, #{name, jdbcType=VARCHAR})
]]>
</insert>
</mapper>
前面的还是一样的写法。dao层依旧:
public interface TestDao {
public void addTest(TestModel testModel);
}
不过有了实现:
@Repository
public class TestDaoImpl implements TestDao{
//dao层实现的方式进行mybatis的调用,就需要在这获取到sqlsession
@Resource
private SqlSessionTemplate sqlSession;
/**
* 测试添加方法
*/
public void addTest(TestModel testModel) {
System.out.println("dao实现的方式");
System.out.println(testModel.getId());
System.out.println(testModel.getSex());
System.out.println(testModel.getName());
// int end = sqlSession.insert("cn.shadow.mapper.TestMapper.addTest", testModel);
int end = sqlSession.insert("TestMapper.addTest", testModel);
System.out.println(end);
}
}
关键的地方其实就在于mapper的名称空间虽然可以随便取了,但是在daoimpl的那里调用还是要写 名称空间+sql的id方式,即
int end = sqlSession.insert("TestMapper.addTest", testModel);
这里要和
<mapper namespace="TestMapper">
<insert id="addTest"
这里对应起来,另外要注入sqlSession。
注意:如果是按照我上面的方式实现,在用第一种方式OK之后,第二种方式可能会报一个错误,创建bean方面的错误,这时候将接口方式的那种删除即可。也就是说只能选择一种方式。