发表于: 2017-10-15 21:51:54
2 652
今天完成的事情:
通过demo(图书管理系统)学习SSM框架(大部分)
通过idea新建mavenwebapp工程:bookmanager 图书预约系统
包含两个表:
book
appointment
工程结构:
配置文件:
①web.xml:
一个seckill-dispatcher的DiepatcherServlet和他的Mapping
用init-param标签初始化:
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
mapping中
<url-pattern>/</url-pattern>设置匹配到任意/xx路径型
②spring-web.xml
自动注册DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter
<mvc:annotation-driven />
老样子,对静态资源的处理
<mvc:default-servlet-handler />
老样子的配置JstlView
添加前后缀。
最后,开启指定包上的注解
<context:component-scan base-package="org.shunly.bookmanager.web"/>
③spring-servlet.xml
<context:component-scan base-package="org.shunly.bookmanager"/>
配置一个事务管理器:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
这个是注解式事务管理:
<tx:annotation-driven transaction-manager="transactionManager"/>
④spring-dao.xml
dataSource、sqlSessionFactory、以及Dao的注入。
使用了c3p0的连接池
部分私有属性:
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!--关闭后不自动commit-->
<property name="autoCommitOnClose" value="false"/>
<!--连接失败后重试次数-->
<property name="acquireRetryAttempts" value="2"/>
<!--超时时间-->
<property name="checkoutTimeout" value="10000"/>
⑤mybatis-config.xml
学习了新的私有属性:
<settings>
<!--开启 jdbc的getGeneratedKeys方法获取数据库自增主键值-->
<setting name="useGeneratedKeys" value="true"/>
<!--开启 列别名替换列名-->
<setting name="useColumnLabel" value="true"/>
<!--开启驼峰命名转换-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
entity实体:与数据库的表相对应的类(pojo)
Book和Appointment
dao数据访问层:数据库操作有关的接口
BookDao包含
①id查询图书 Book selectById(long id)
②查询所有图书 List<Book> selectAll(@Param("offset")int offset, @Param("limit") int limit);
③更新(减少)馆藏数量 int reduceNumber( long bookId);
AppointmentDao包含
①预约记录插入
int insertAppointment(@Param("bookId") long bookId, @Param("studentId") long studentId);
②通过主键查询预约记录
Appointment selectByKeyFromBook(@Param("bookId") long bookId, @Param("studentId") long studentId);
enums枚举:存放和异常有关的状态
AppointStateEnum:
两个属性:state,stateInfo
一个包含这两个属性的构造器
SUCCESS(1, "预约成功"), NO_NUMBER(0, "库存不足"), REPEAT_APPOINT(-1, "重复预约"), INNER_ERROR(-2, "系统异常");
该方法遍历整个枚举的值,如果状态码匹配,则返回这个枚举类,否则返回null;
public static AppointStateEnum stateod(int index){
for(AppointStateEnum state:values()){
if(state.getState() == index){
return state;
}
}
return null;
}
dto数据传输层:传输返回数据给service
AppointExecution 封装预约结果信息
四个属性:bookId, state(状态码), stateInfo(状态信息), Appointment(预约信息类)
两个构造器:成功的则给Appointment赋值,失败的则没有。
exception异常:处理异常的。。(这样定义异常和处理是比较正确的么)
分别处理库存不足异常、预约重复异常、预约异常。
继承RuntimeException
service业务接口:
根据使用者角度有三个方法:
①Book getById(long bookId);
② List<Book> getList();
③AppointExecution appoint(long bookId, long studentId);
ServiceImp业务实现:
两个Dao接口属性BookDao、AppointmentDao
使用BookDao的selectById和selectAll方法实现①和②。
方法③:利用update的返回值判断是否库存足够,再通过insert返回值判断是否重复,最后得到预约成功的信息。
@Transactional
public AppointExecution appoint(long bookId, long studentId) {
try {
int update = bookDao.reduceNumber(bookId);
if (update <= 0) {
throw new NoNumberException("no number");
} else {
int insert = appointmentDao.insertAppointment(bookId, studentId);
if (insert <= 0) {
throw new RepeatAppointException("repeat appoint");
} else {
Appointment appointment = appointmentDao.selectByKeyFromBook(bookId, studentId);
return new AppointExecution(bookId, AppointStateEnum.SUCCESS, appointment);
}
}
}catch (NoNumberException e1){
throw e1;
}catch (RepeatAppointException e2){
throw e2;
}catch (Exception e){
logger.error(e.getMessage(),e);
throw new AppointException(("appoint inner error:" + e.getMessage()));
}
}
缺省BookController和Result(封装json返回结果)
涉及到了Json,暂不表。
测试结果:
①BookDaoTest
②AppointmentDaoTest
③BookServiceImpTest
明天计划的事情:
着手完成任务2,json和JsonTagLib
遇到的问题:
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
新版本的jdbc驱动。。。class变更为com.mysql.cj.jdbc.Driver 注意修改。
收获:
小知识:
①使用mybatis时,Dao接口中的方法如果参数两个及以上,使用@Param("xxx")来注解参数xxx。
②ORDER BY xx是排序语句
③mysql忽略主键冲突,避免重复插入的方法:
INSERT IGNORE INTO `table_name` (`column1`...) VALUES(`value1`...);
REPLACE INTO `table_name`(`colomn1`, ...) VALUES (...);
当遇到重复时
IGNORE 忽略该句,返回0。
REPLACE 从表中删除受影响的行,并重新插入。返回一个数,来指示受影响的行的数目。该数是被删除和被插入的行数的和。
④联合查询 INNER JOIN
用法示例:
SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
评论