SM的开发步骤
1、在中央库提供的web应用中查询依赖的GAV坐标值
- spring-context-support提供Spring的IoC容器
- spring-jdbc提供Spring针对JDBC编程的支持,并按照传递依赖自动添加spring-tx事务支持
- spring-web提供spring针对web编程的支持
- mybatis声明依赖mybatis框架
- mybatis-spring整合Spring和MyBatis框架
- HikariCP提供连接池依赖
- ojdbc8是oracle11g的jar包
为了解决默认使用JavaSE-1.5的问题,添加一个插件配置【局部配置方式】
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2、创建用户和数据表
启动Oracle数据库就是启动2个服务:
- OracleServiceORCL
- OracleOraDb11g_home1TNSListener
使用sqlplus操作ORCL数据库
在cmd中输入命令sqlplus / as sysdba
create user yanjun identified by 123456; --创建用户yanjun,口令为123456
grant connect,resource,dba to yanjun; -- 通过使用角色给新用户授权
conn yanjun/123456 -- 切换当前用户到新用户
create table tb_users(
id number(18) primary key, -- 代理主键,类似于mysql中的bigint
username varchar2(20) not null unique,
password varchar2(20) not null,
birth date default sysdate, -- sysdate是系统提供的函数,用于获取数据库服务器的系统当前时
sex number(1) default 1,
salary number(8,2) default 0.0
);
-- 为了实现主键自增长效果,需要创建序列对象
create sequence seq_users;
-- 使用时可以通过序列对象的伪列直接使用nextval currval
insert into tb_users values(seq_users.nextval,'yanjun','12345',to_date('1989-4-30','yyyy-MM-dd'),1);
3、使用mybatis提供的官方插件执行反向映射
pom.xml中添加插件配置
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
<configurationFile>src/test/resources/generatorConfig.xml</configurationFile>
</configuration>
</plugin>
在目录src/test/resources目录下创建反向映射配置文件generatorConfig.xml
<table tableName="tb_users" domainObjectName="User"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false"></table>
使用菜单Run as—Maven build…----在goals中输入mybatis-generator:generate
检查方向映射生成的实体类、Mapper接口和Mapper.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.yan.dao.UserMapper">
<resultMap id="BaseResultMap" type="com.yan.entity.User">
<id column="ID" jdbcType="NUMERIC" property="id" />
<result column="USERNAME" jdbcType="VARCHAR"
property="username" />
<result column="PASSWORD" jdbcType="VARCHAR"
property="password" />
<result column="BIRTH" jdbcType="DATE" property="birth" />
<result column="SEX" jdbcType="BOOLEAN" property="sex" />
<result column="SALARY" jdbcType="NUMERIC" property="salary" />
</resultMap>
<sql id="Base_Column_List">
ID, USERNAME, PASSWORD, BIRTH, SEX, SALARY
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Long"
resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from TB_USERS
where ID = #{id,jdbcType=NUMERIC}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete from TB_USERS
where ID = #{id,jdbcType=NUMERIC}
</delete>
<insert id="insertSelective" parameterType="com.yan.entity.User">
<selectKey keyProperty="id" order="BEFORE" resultType="long">
select seq_users.nextval from dual
</selectKey>
insert into TB_USERS
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
ID,
</if>
<if test="username != null">
USERNAME,
</if>
<if test="password != null">
PASSWORD,
</if>
<if test="birth != null">
BIRTH,
</if>
<if test="sex != null">
SEX,
</if>
<if test="salary != null">
SALARY,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=NUMERIC},
</if>
<if test="username != null">
#{username,jdbcType=VARCHAR},
</if>
<if test="password != null">
#{password,jdbcType=VARCHAR},
</if>
<if test="birth != null">
#{birth,jdbcType=DATE},
</if>
<if test="sex != null">
#{sex,jdbcType=BOOLEAN},
</if>
<if test="salary != null">
#{salary,jdbcType=NUMERIC},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective"
parameterType="com.yan.entity.User">
update TB_USERS
<set>
<if test="username != null">
USERNAME = #{username,jdbcType=VARCHAR},
</if>
<if test="password != null">
PASSWORD = #{password,jdbcType=VARCHAR},
</if>
<if test="birth != null">
BIRTH = #{birth,jdbcType=DATE},
</if>
<if test="sex != null">
SEX = #{sex,jdbcType=BOOLEAN},
</if>
<if test="salary != null">
SALARY = #{salary,jdbcType=NUMERIC},
</if>
</set>
where ID = #{id,jdbcType=NUMERIC}
</update>
</mapper>
映射接口
public interface UserMapper {
int deleteByPrimaryKey(Long id);
int insertSelective(User record);
User selectByPrimaryKey(Long id);
int updateByPrimaryKeySelective(User record);
}
实体类
@Data
public class User implements Serializable{
private static final long serialVersionUID = -2071156397727424886L;
private Long id;
private String username;
private String password;
private Date birth;
private Boolean sex;
private Double salary;
}
4、添加Spring的核心配置文件resources/applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置數據源 -->
<context:property-placeholder
location="classpath*:database.properties" />
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
p:username="${jdbc.username}" p:password="${jdbc.password}"
p:driverClassName="${jdbc.driver}" p:jdbcUrl="${jdbc.url}"
destroy-method="close" />
</beans>
数据链接相关配置 resources/database.properties
jdbc.driver=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:ORCL
jdbc.username=yanjun
jdbc.password=123456
5、单元测试
import java.sql.Connection;
import javax.sql.DataSource;
import static org.junit.Assert.*; //静态导入
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class DataSourceTest {
@Autowired
private DataSource ds;
@Test
public void testConnection() throws Exception {
Connection conn = ds.getConnection();
System.out.println(conn);
assertNotNull(conn);
}
}
6、MyBatis相关配置
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="dataSource" />
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
p:sqlSessionFactoryBeanName="sqlSessionFactory"
p:basePackage="com.yan.dao" /> 自动扫描
要求Mapper接口所在的包名称和Mapper.xml映射文件的目录名称一致
7、单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
User user=new User();
user.setUsername("张前端");
user.setPassword("666666");
int len=userMapper.insertSelective(user);
Assert.assertEquals(1, len);
Assert.assertNotNull(user.getId());
}
}
8、添加业务
- 接口
- 业务实现 @Service
- 自动扫描
@Service
public class UserServImpl implements IUserServ {
@Autowired
private UserMapper userMapper;
@Override
public boolean create(User user) {
Assert.notNull(user,"用户信息为空!");
Assert.hasText(user.getUsername(),"用户名称为空!");
Assert.hasText(user.getPassword(),"用户口令为空!");
int len=userMapper.insertSelective(user);
return len>0;
}
}
主动组件扫描的配置
<context:component-scan base-package="com.yan"/>
9、添加声明式事务管理
在applicationContext.xml中进行配置,为了简化配置,需要引入tx名空间
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />
<tx:annotation-driven/>
在业务类上添加注解,说明事务的5方面的配置信息
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)//针对只读查询
@Service
public class UserServImpl implements IUserServ {
@Autowired
private UserMapper userMapper;
@Transactional(readOnly = false,propagation = Propagation.REQUIRED) //针对增删改
public boolean create(User user) {
Assert.notNull(user,"用户信息为空!");
Assert.hasText(user.getUsername(),"用户名称为空!");
Assert.hasText(user.getPassword(),"用户口令为空!");
int len=userMapper.insertSelective(user);
return len>0;
}
}
10、添加web应用
表现层框架使用SpringMVC
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
springMVC框架采用的是前端控制器模式,所以需要在web.xml中配置一个总前端控制器
web.xml配置父容器—管理除了和web相关的其它受管bean,这个ContextLoaderListener监听器在容器启动时自动初始化IoC/DI容器【按照contextConfigLocation配置】,并将容器存放在application中,供所有的用户共享使用
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:app*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
修改配置使父容器中不管理@Controller
<context:component-scan base-package="com.yan">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
web.xml配置前端控制—子容器—管理和web相关的所有受管bean
<servlet>
<servlet-name>yan</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>yan</servlet-name>
<url-pattern>*.do</url-pattern> 映射后缀可以是任意后缀
</servlet-mapping>
设置前端控制器的名称为【servlet-name=yan】,所以默认的配置文件位于/WEB-INF/下,名称为yan-servlet.xml,也可以通过servlet配置参数进行修改
为了简化web应用配置,可以引入一个名空间mvc
<?xml version="1.0" encoding="UTF-8"?>
<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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<mvc:annotation-driven /> 注解驱动 @RequestMapping才能生效
<context:component-scan base-package="com.yan.action" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/content/" p:suffix=".jsp" p:viewClass="org.springframework.web.servlet.view.JstlView"/> 视图解析器,可以将逻辑视图名转换为物理地址 【prefix+逻辑视图名+suffix】
</beans>
11、定义控制器类
@Controller //声明控制器类
@RequestMapping("/") 类上的地址映射,相当于是类中所有映射地址的名空间
public class UserController {
@RequestMapping(value="login.do",method = RequestMethod.GET) //如果get请求访问/login.do时调用这个方法,
public String login()throws Exception{
System.out.println("login.....");
return "user/login"; //逻辑地址名
}
@RequestMapping(value="login.do",method=RequestMethod.POST)
public String login(User user)throws Exception{
return null;
}
}
12、web应用测试
添加一个jetty插件
mvn jetty:run-war