SSM框架是由spring,springMVC,Mybatis整合,先从每个框架个体开始。
Mybatis
他和hibernate很相似是数据访问层的框架,但和hibernate不同的是Mybatis是使用SQL语句检索,还会自动生成一些常用语句。而hibernate使用的HQL语句,自己添加检索语句时略显麻烦。
首先配置Mybatis,它配置原理和hibernate差不多,都是直接通过映射数据库表生成实体类和Dao层的数据访问相关类,但它是从外部生成移到到项目中的。
1.创建项目,将Mybaitis相关jar包拷贝到项目lib文件夹
2.外部打开generator文件夹,记得将它放到D盘根目录,generator中的文件如下
3.将generator.xml文件使用HBuilder打开,如果用记事本打开会自动添加一些东西,影响后续操作,打开后其中代码如下。
这个配置文件只需要改变几个小地方,jdbcConnection标签中URL路径中改变自己的数据库名,
javaModelGenertor标签targetPackage属性,实体类的生成位置
sqlMapGenerator同样输入映射文件的包名和位置
javaClientGenerator就是dao层的类
最下面的table就是要生成的表,第一个属性是表名,第二个属性是生成的类名
其实配置的时候就能发现有好多属性路径是D盘的generator的src文件夹,这就代表要生成的包和文件都在我们之前的genarrator,包括自动生成要的sql驱动也在这里。
设置完后回到generator点击auto.bat文件执行,再看看src中是否有我们设置好的包名和类文件,有就说明配置没有出现问题,生成成功。
4.将src中的文件移到项目的src文件夹中,再来看一下其中有哪些文件,首先是dao层中,配置时就写好了配置文件和dao层类都再dao包中。
先看xml文件中有什么?代码太多就只截取部分
<?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.lb.dao.AuthorMapper" >
<resultMap id="BaseResultMap" type="com.lb.entity.Author" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="username" property="username" jdbcType="VARCHAR" />
<result column="password" property="password" jdbcType="VARCHAR" />
<result column="email" property="email" jdbcType="VARCHAR" />
<result column="address" property="address" jdbcType="VARCHAR" />
<result column="phone" property="phone" jdbcType="VARCHAR" />
<collection property="blogs" ofType="Blog" column="id" >
<id column="bid" property="id" jdbcType="INTEGER"></id>
<result column="title" property="title" jdbcType="VARCHAR" />
<collection property="comments" ofType="Comment" column="cid">
<id column="cid" property="id" jdbcType="INTEGER"></id>
<result column="content" property="content" jdbcType="VARCHAR" />
</collection>
</collection>
</resultMap>
<sql id="Base_Column_List" >
id, username, password, email, address, phone
</sql>
<select id="selectByBlogs" resultType="Blog" parameterType="java.lang.Integer">
select id,title,content
from blog where author_id=#{id}
</select>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from author
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from author
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.lb.entity.Author" >
insert into author (id, username, password,
email, address, phone
)
values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
#{email,jdbcType=VARCHAR}, #{address,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}
)
</insert>
</mapper>
先看resultMap标签中的,里面每个标签对应着表里的字段,id代表主键,其中属性cloumn代表着实体类中的属性名,propety代表sql代码执行返回的字段名。
最后就是这个collection标签,它是一对多“一”方的标签,这个标签是要自己手动加上去的,它其中的标签也对应着字段,这里为了简洁只写了两个主要字段,其中有一个ofTYpe属性是该列返回的对象,是在“一”方的配置文件里“多”方的属性。
先缕一缕表的关系,author是主表,blog表有author表主键的外键,Comment表有blog表主键的外键。
所以这里collection是有一个嵌套将三个表的关联关系一次查出来了。
至于下面的代码也很容易就看出来了,是自动生成的增删改查功能的SQL语句,刚刚也提到collection标签是自己写的,为的是要将表关联起来,所以也要加一个相应的多表查询SQL语句。就是下面这段,将resultMap中提到的字段全部查询出来,只需要知道author的id就可以查询该id关于所有表的信息。将该查询的ID值复制到AuthorMapper文件中,写成一个方法,查询的ID属性值必须和方法名相同
public interface AuthorMapper {
int deleteByPrimaryKey(Integer id);
int insert(Author record);
int insertSelective(Author record);
Author selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(Author record);
int updateByPrimaryKey(Author record);
Author selectAuthorAndBlogsAndComments(Integer id);
}
5.写一个Mybaitis的配置文件,写入下面代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 允许JDBC支持生成的键 -->
<setting name="useGeneratedKeys" value="true"/>
</settings>
<typeAliases>
<!-- 配置数据类型的别名 -->
<typeAlias type="com.lb.entity.Blog" alias="Blog"/>
<typeAlias type="com.lb.entity.Author" alias="Author"/>
<typeAlias type="com.lb.entity.Comment" alias="Comment"/>
</typeAliases>
<!-- 默认的环境ID -->
<environments default="development">
<!-- 每个environment元素定义的环境ID -->
<environment id="development">
<!-- 事务处理方式 -->
<transactionManager type="JDBC" />
<!-- 数据源配置 -->
<dataSource type="POOLED">
<!-- 数据库JDBC驱动 -->
<property name="driver" value="com.mysql.jdbc.Driver" />
<!-- 数据库URL -->
<property name="url" value="jdbc:mysql://localhost:3306/blog_db?characterEncoding=UTF-8" />
<!-- 数据库用户 -->
<property name="username" value="root" />
<!-- 密码 -->
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- 配置映射文件 -->
<mapper resource="com/lb/dao/BlogMapper.xml"/>
<mapper resource="com/lb/dao/AuthorMapper.xml"/>
<mapper resource="com/lb/dao/CommentMapper.xml"/>
</mappers>
</configuration>
这个配置文件就很简单了,给实体类其别名(别名就是在dao层的xml文件要使用的返回对象类型),连接的数据库信息,映射dao层的文件
6.创建一个mybatis的session工厂,与hibernate一样,通过这个session工厂连接业务逻辑层和数据访问层。
package com.lb.dao;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisSessionFactory {
private final static SqlSessionFactory SQL_SESSION_FACTORY;
static{
org.apache.ibatis.logging.LogFactory.useLog4JLogging(); //开启日志,目的显示SQL语句
String path = "mybatis-config.xml";
Reader reader = null;
try {
reader = Resources.getResourceAsReader(path);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
SQL_SESSION_FACTORY = new SqlSessionFactoryBuilder().build(reader);
}
public static SqlSessionFactory getSessionFactory(){
return SQL_SESSION_FACTORY;
}
public static SqlSession getSession(){
return SQL_SESSION_FACTORY.openSession();
}
}
7.调用显示数据,完成查询流程
package com.lb.service;
import org.apache.ibatis.session.SqlSession;
import com.lb.dao.AuthorMapper;
import com.lb.dao.MybatisSessionFactory;
import com.lb.entity.Author;
public class AuthorService {
private SqlSession session=MybatisSessionFactory.getSession();//获取session工厂
private AuthorMapper authorDao=session.getMapper(AuthorMapper.class);//通过session工厂获得dao层类
public Author selectByPrimaryKey(Integer id) {
return authorDao.selectByPrimaryKey(id);
}
public Author selectAuthorAndBlogsAndComments(Integer id){
return authorDao.selectAuthorAndBlogsAndComments(id);
}
}
public static void main(String[] args) {
AuthorService authorService=new AuthorService();
Author author =authorService.selectAuthorAndBlogsAndComments(1);
System.out.println(author);
System.out.println(author.getUsername());
for (Blog blog:author.getBlogs()) {
System.out.println(blog.getTitle());
System.out.println(blog.getContent());
for (Comment comment : blog.getComments()) {
System.out.println(comment.getContent());
}
}
}
SpringMVC
和struts一样是界面层框架,访问方式也很相似
首先是配置框架,在项目的web.xml文件中配置中添加相关配置和MVC的拦截(这里和struts相似)
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>viewSpace</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>viewSpace</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
这个servlet的名字和外部创建的xml文件名相关联,命名格式是 名字-servlet.xml
外部viewSpace-servlet.xml中只需要写一个标签,内容是包名,访问时它会自动扫描该包下的控制器
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.lb.action"></context:component-scan>
</beans>
在该包下创建一个类,因为SpringMVC不会像struts那样会自动识别,所以需要回传值和接收值
@Controller//注解此类是一个控制器
@RequestMapping("/")//前端页面提交的路径目录,这里写的是所有路径
public class AuthorController {
@Autowired
private AuthorService authorService;
@RequestMapping("test")//访问时的路径,跟struts的action id一样会扫描到此方法并执行
public ModelAndView selectAuthor(
@RequestParam("id") int id//从前台传回的值
) {
ModelAndView andView=new ModelAndView();//创建视图模型
andView.setViewName("index.jsp");//加入一个视图页面
Author author=authorService.selectByPrimaryKey(id);
andView.addObject("author",author);//类似session用法,key值和内容
return andView;//返回视图
}
}
框架整合
在了解了两个框架后要整合也变得简单了,一个负责数据访问,一个负责前端显示,但它们是各做各座,要整合在一起就只有通过spring整合,将它们所有的处理交给spring完成。
dao层中的SQL session工厂不需要了可以删掉,还有mybatis.xml文件中的数据库配置信息也不需要了,把这部分的代码删掉,只需留下映射xml文件的代码就行了。
现在移交所有权利,处理都交给spring
<context:component-scan base-package="com.lb"/>
<bean id="validao" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"></bean>
<bean id="dataSouce" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/blog_db?characterEncoding=utf-8"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="SqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="dataSource" ref="dataSouce"></property>
</bean>
<bean id="authorDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="SqlSession"></property>
<property name="mapperInterface" value="com.lb.dao.AuthorMapper"></property>
</bean>
将SQLsession工厂和mybatis.xml中的数据库信息配置在扫描控制器的 *-servlet.xml文件中,
这样改造基本上就完成了,接下来就是在各层加上注解,理清其中的依赖关系
依次在各层中,使用@Repository(dao)、@Service(service)和@Controller(controller)注解
在依赖类中,使用@Autowired(调用上一层类的对象)对接口声明
dao层
@Repository
public interface AuthorMapper {
service层
@Service
public class AuthorService {
@Autowired
private AuthorMapper authorDao;
contrller层
@Controller
@RequestMapping("/")
public class AuthorController {
@Autowired
private AuthorService authorService;
存了很久