MyBatis学习笔记
MyBatis框架简介
♥开发中要考虑代码的性能:
①避免多表查询;
②避免过多的复杂的逻辑循环控制;
③避免同一数据的重复查询处理,使用缓存机制进行处理。
MyBatis设计思想:(不考虑数据库移植,这也是最大缺点)
①代码更加简单
②不过多考虑复杂的数据库操作
最大优点:体积小,响应速度快(王道),避免了复杂的逻辑性的操作,提供映射支持
与Hibernate区别:
①面对数据库的移植操作,Hibernate一定是不二选择(但如果是不需要数据库移植的环境,Hibernate没有优势)
②Hibernate根据配置文件动态转换为SQL语句(缺点:复杂度高)
③Hibernate配置复杂,如果配置不当,直接带来严重的性能问题
开发第一个MyBatis
♥搭建MyBatis开发环境(实现数据增加操作):导入包,编写mybatis.cfg.xml(如下)
<?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> <!-- 数据库的连接配置--> <environments default="development"> <environment id="development"> <!-- 使用JDBC来实现数据库的事务控制 --> <transactionManager type="jdbc"></transactionManager> <!-- 连接类型 --> <!-- POOLED:表示所有的数据库连接都要在数据库连接池之中保存,性能最好 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="mysqladmin"/> </dataSource> </environment> </environments> </configuration>
编写vo类,然后编写映射文件
<?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="ycit.sth.vo.mapping.MemberNS"> <!-- 定义数据增加所使用的SQL语句,id为调用名称,与命名空间结合使用,不能够重复--> <insert id="doCreate" parameterType="ycit.sth.vo.Member"> INSERT INTO `member`(mid,name,age,birthday,salary) VALUES(#{mid},#{name},#{age},#{birthday},#{salary}) </insert> </mapper>
所有的映射文件必须在mybatis.cfg.xml中进行映射
<!-- 编写映射文件的路径-->
<mappers>
<mapper resource="ycit/sth/vo/mapping/Member.xml"></mapper>
</mappers>
MyBatis使用的操作类:读取配置Reader 连接工厂SqlSessionFactory 连接对象SqlSession
对比Hibernate:读取配置Configuration 连接工厂SessionFactory 连接对象Session
配置测试类
public class TestMemberInsert { public static void main(String[] args) throws Exception{ //1.读取myBatis的核心配置文件 mybatis.cfg.xml Reader reader= Resources.getResourceAsReader("mybatis.cfg.xml"); //2.创建SqlSessionFactory工厂类 SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(reader); //3.通过工厂类取得SqlSession对象 SqlSession session=factory.openSession(); //4.进行数据的保存 Member vo=new Member(); vo.setMid("小哥"); vo.setName("张起灵"); vo.setAge(100); vo.setBirthday(new Date()); vo.setSalary(888888.88); int len=session.insert("ycit.sth.vo.mapping.MemberNS.doCreate",vo);//设置要执行的SQL语句 session.commit(); System.out.println("操作影响的行数:"+len); session.close(); reader.close(); } }
问题1:如果id是自动增长列,要取得增长后的id 值,增加配置即可,无需再写一条SQL语句
<insert id="" parameterType="" keyProperty="自动增长列" useGeneratedKeys="true">SQL语句</insert>
问题2:配置文件内每次配置参数都要加上包.名称(j见上面蓝色),太长,不方便维护,在mybatis.cfg.xml可以进行别名设置
<!-- 别名设置-->
<typeAliases>
<package name="ycit.sth.vo"/>
</typeAliases>
配置日志
拷贝log4j.properties文件及所需的jar包
让日志文件进行输出显示,必须手工修改log4j.properties文件
log4j.logger.ycit.sth.vo.mapping.MemberNS=TRACE 命名空间
写包名该包下的所有xml都可以日志输出
自定义MyBatisSessionFactory
/** * ClassName:MyBatisSessionFactory * Package:ycit.sth.util * Description: 本类主要负责SqlSessionFactory与SqlSession接口对象的取得 * 以及负责重新连接以及关闭的处理操作 * @Date:2021/2/1 12:20 * Author:沙天慧 */ public class MyBatisSessionFactory { private static final String CONFIG_FILE="mybatis.cfg.xml"; //保存SqlSession接口对象,主要被不同的层做引用操作 private static ThreadLocal<SqlSession> threadLocal=new ThreadLocal<SqlSession>(); //用于通过它操作二级缓存以及重新取得SqlSession的配置 private static SqlSessionFactory factory=null; //主要是读取mybatis.cfg.xml文件 private static InputStream input=null; static { rebuildSessionFactory(); //静态代码块,在类加载的时候创建SqlSessionFactory接口对象 } /** * 取得当前连接的SqlSession对象,如果没有,则通过SqlSessionFactory创建新的SqlSession, * 如果当前存在该对象,则通过ThreadLocal取得 * @return SqlSession对象 */ public static SqlSession getSession(){ SqlSession session=threadLocal.get();//通过ThreadLocal取得 if (session==null){ //没有SqlSession对象 if (factory==null){ //没有工厂 rebuildSessionFactory();; } session=factory.openSession(); //创建新的session对象 threadLocal.set(session); } return session; } public static SqlSessionFactory getSessionFactory(){ return factory; } /** * 重新建立新的SqlSessionFactory对象 */ public static void rebuildSessionFactory(){ try { input= Resources.getResourceAsStream(CONFIG_FILE); factory= new SqlSessionFactoryBuilder().build(input); } catch (IOException e) { e.printStackTrace(); } } public static void close(){ SqlSession session=threadLocal.get(); threadLocal.set(null); if (session!=null){ session.close(); if (input!=null){ try { input.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
更新删除操作
<update id="doUpdate" parameterType="News"> UPDATE news SET title=#{title},pubdate=#{pubdate} WHERE nid=#{nid} </update> <delete id="doRemove" parameterType="int"> delete FROM news WHERE nid=#{id} 一个参数随便什么名字都可以 </delete>
查询操作
当数据库的列名和属性名不一致时,除了在SQL语句写上别名,最好的方法是设置映射关系,在每个映射文件中配置。
<!-- 结果转换映射-->
<resultMap id="NewsResultMap" type="News"> <id property="nid" column="nid"></id> <result property="title" column="title"></result> <result property="pubdate" column="pubdate"></result> </resultMap> <select id="findById" parameterType="int" resultMap="NewsResultMap"> //查询单个数据 select nid,title,pubdate FROM news WHERE nid=#{id} </select>
数据的分页查询
MyBatis对于参数的传递分为两种形式:
①以内容替换的方式设置参数:${替换变量}
②传递的操作的数值:#{内容}
<!-- 分页查询 -->
<!-- Map集合的特点是根据Key取得对应的value数据,MyBatis里发现有多个参数就传Map-->
<select id="findAllSplit" resultMap="NewsResultMap" parameterType="java.util.Map">
SELECT nid,title,pubdate FROM news WHERE ${column} LIKE #{keyword} LIMIT #{start},#{lineSize}</select>
<!-- 统计数据行数-->
<select id="getAllCountSplit" resultType="int" parameterType="java.util.Map">
SELECT COUNT(*) FROM news WHERE ${column} LIKE #{keyword}
</select>
缓存机制
♥缓存可以减少数据库的访问操作,以达到性能的提升。
MyBatis提供两类缓存,一级缓存(SqlSession级,永远存在)、二级缓存(SqlSessionFactory,需要进行配置)
一级缓存
更改缓存数据会影响后续数据的查询,但不会修改数据库的数据
如果之前的数据发生事务提交处理,会将缓存的数据清除掉,如果有需要,可以利用SqlSession接口的方法clearCache()手工进行缓存的清除
二级缓存
二级缓存的配置:
修改mybatis.cfg.xml:
<settings>
<!-- 启用二级缓存配置 -->
<setting name="cacheEnabled" value="true"/>
</settings>
在你需要缓存的对象上(*.xml)进行缓存的配置 加上<cache/>
【注】
①第一个Session关闭后才能将内容写入缓存
②要进行缓存的对象所在的类必须实现Serializable接口,负责出错
对于不需要使用二级缓存的单独配置 useCache=false
默认缓存所使用的缓存处理算法:LRU(最近最少使用算法)
动态SQL
♥利用配置文件来实现判断与循环的效果
if 语句
<select id="findAllByTitle" parameterType="News" resultMap="NewsResultMap"> SELECT nid ,title,pubdate FROM news <if test="title!=null"> WHERE title=#{title} </if> </select>
不传参数就查询全部,此时的SQL语句可以动态的进行处理
choose语句
当我们不想使用所有的查询条件,只想选择其中的一个,此时使用choose标签可以解决问题
实现当nid不空时根据nid查,当nid为空title不空时根据title查,当nid,title均为空时,根据pubdate查,都为空,查询全部
<select id="" parameterType="News" resultMap="NewsResultMap"> SELECT nid ,title,pubdate FROM news <where> <choose> <when test="nid!=''and nid!=null">nid=#{nid}</when> <when test="title!=''and title!=null">title=#{title}</when> <when test="pubdate!=''and pubdate!=null">pubdate=#{pubdate}</when> </choose> </where> </select>
foreach语句
其标签的属性:
collection:collection 属性的值有三个分别是 list、array、map 三种,分别对应的参数类型为:List、数组、map 集合。
item :表示在迭代过程中每一个元素的别名
index :表示在迭代过程中每次迭代到的位置(下标)
open :前缀
close :后缀
separator :分隔符,表示迭代时每个元素之间以什么分隔
查询 id为1,2,3的信息
<select id="" parameterType="java.util.List" resultMap="NewsResultMap"> SELECT nid ,title,pubdate FROM news WHERE nid IN <foreach collection="list" index="index" item="nid" open="(" separator="," close=")">#{nid}</foreach> </select>
set语句
当在update中使用if标签,如果有if没有执行,会因为多余的逗号导致错误。使用 set 标签可以将动态的配置 set关键字,和剔除追加到条件末尾的任何不相关的逗号。使用 set+if 标签修改后,如果某项为 null 则不进行更新,而是保持数据库原值。
<update id="findAllByTitle" parameterType="News" > UPDATE news <set> <if test="title !='' and title !=null">title=#{title},</if> <if test="pubdate !=null">pubdate=#{pubdate}</if> </set> WHERE nid=#{nid} </update>
Annotation配置
♥写完DAO接口,一般要实现其子类,也可以使用注解配置
public interface INewsDAO { @Insert("INSERT INTO news(title,pubdate) VALUES(#{title},#{pubdate})") @SelectKey(before = false,keyProperty = "nid",resultType = java.lang.Integer.class,statement = "SELECT LAST_INSERT_ID()") public boolean doCreate(News vo) throws Exception; //返回主键,before = false表示在执行之后 @Update("UPDATE news SET title=#{title},pubdate=#{pubdate} WHERE nid=#{nid}") public boolean doUpdate(News vo) throws Exception; @Delete("DELETE FROM news WHERE nid=#{id}") public boolean doRemove(Integer id) throws Exception; @Select("SELECT nid,title,pubdate FROM news WHERE nid=#{id}") public News findById(Integer id) throws Exception; @Select("SELECT nid,title,pubdate FROM news ") public List<News> findAll() throws Exception; @Select("SELECT nid,title,pubdate FROM news WHERE #{column} LIKE #{keyword} LIMIT #{start},#{lineSize}") public List<News> findAllSplit( @Param("column") String column, @Param("keyword") String keyword, @Param("currentPage") Integer currentPage, @Param("lineSize")Integer lineSize) throws Exception; @Select("SELECT COUNT(*) FROM news WHERE ${column} LIKE #{keyword}") public Integer getAllCount( @Param("column") String column, @Param("keyword") String keyword) throws Exception; }
如果要使用这个接口进行数据操作,要修改MyBatisSessionFactory.java
public static void rebuildSessionFactory(){ try { input= Resources.getResourceAsStream(CONFIG_FILE); factory= new SqlSessionFactoryBuilder().build(input); factory.getConfiguration().addMappers("ycit.sth.dao"); } catch (IOException e) { e.printStackTrace(); } }
Annotation不能够实现实现动态SQL,所以在项目中不会使用。
识别器
♥识别器指的是在一张数据表中可以描述多种实体的关系
Member有两个子类Student,Worker, 根据id查询返回结果是student还是worker根据flag标记
<mapper namespace="ycit.sth.vo.mapping.MemberNS"> <!-- resultMap是在查询返回结果的时候才会起作用,那么就意味着数据的更新跟此配置无关--> <resultMap id="MemberResultMap" type="Member"> <id property="mid" column="mid"></id> <result property="name" column="name"></result> <result property="age" column="age"></result> <discriminator javaType="String" column="flag"> <case value="学生" resultType="Student"> <result property="score" column="score"></result> <result property="school" column="school"></result> </case> <case value="工人" resultType="Worker"> <result property="company" column="company"></result> <result property="salary" column="salary"></result> </case> </discriminator> </resultMap> <insert id="doCreateStudent" parameterType="Student"> INSERT INTO `member` (mid,name,age,flag,school,score) VALUES(#{mid},#{name},#{age},'学生',#{school},#{score}) </insert> <insert id="doCreateWorker" parameterType="Worker"> INSERT INTO `member` (mid,name,age,flag,company,salary) VALUES(#{mid},#{name},#{age},'工人',#{company},#{salary}) </insert> <select id="findByStudentId" parameterType="String" resultMap="MemberResultMap"> SELECT mid,name,age,flag,school,score FROM `member` WHERE mid=#{mid} AND flag='学生' </select> <select id="findByWorkerId" parameterType="String" resultMap="MemberResultMap"> SELECT mid,name,age,flag,company,salary FROM `member` WHERE mid=#{mid} AND flag='工人' </select> </mapper>
一对一数据关联
♥两张表memebr_login, member_details,一对一关系
MemberLogin.xml
<mapper namespace="ycit.sth.vo.mapping.MemberLoginNS"> <resultMap id="MemberLoginResultMap" type="MemberLogin"> <id property="mid" column="mid"></id> <result property="password" column="password"></result> <!-- 该级联操作发生在数据查询的时候进行,表示查询返回的是MemberLoginResultMap时,执行级联 --> <association property="details" javaType="MemberDetails" column="mid" select="ycit.sth.vo.mapping.MemberDetailsNS.findById"></association> </resultMap> <select id="findById" parameterType="java.lang.String" resultMap="MemberLoginResultMap"> SELECT mid,password FROM member_login WHERE mid=#{mid} </select> <insert id="doCreate" parameterType="MemberLogin"> INSERT INTO member_login(mid,password) VALUES(#{mid},#{password}) </insert> </mapper>
MemberDetails.xml
<mapper namespace="ycit.sth.vo.mapping.MemberDetailsNS"> <resultMap id="MemberDetailsResultMap" type="MemberDetails"> <id property="mid" column="mid"></id> <result property="name" column="name"></result> <result property="age" column="age"></result> </resultMap> <select id="findById" parameterType="java.lang.String" resultMap="MemberDetailsResultMap"> SELECT mid,name,age FROM member_details WHERE mid=#{mid} </select> <insert id="doCreate" parameterType="MemberDetails"> INSERT INTO member_details(mid,name,age) VALUES(#{mid},#{name},#{age}) </insert> </mapper>
一对多数据关联(重难点)
♥两张表 type 和subtype
【注】如果使用级联操作,select="ycit.sth.vo.mapping.SubTypeNS.findByType" ,会出现1+N次查询,不合适,千万不能使用
Type.xml
<mapper namespace="ycit.sth.vo.mapping.TypeNS"> <resultMap id="TypeResultMap" type="Type"> <id property="tid" column="tid"></id> <result property="title" column="title"></result> <collection property="subTypes" column="tid" javaType="java.util.List" ofType="SubType"></collection> 这个地方注意上面的注 </resultMap> <insert id="doCreate" parameterType="Type"> INSERT INTO type(title) VALUES(#{title}) </insert> <select id="findById" parameterType="Integer" resultMap="TypeResultMap"> SELECT tid,title FROM type WHERE tid=#{tid} </select> </mapper>
SubType.xml
<mapper namespace="ycit.sth.vo.mapping.SubTypeNS"> <resultMap id="SubTypeResultMap" type="SubType"> <id property="stid" column="stid"></id> <result property="title" column="title"></result> <association property="type" javaType="Type" column="tid" resultMap="ycit.sth.vo.mapping.TypeNS.TypeResultMap"></association> </resultMap> <insert id="doCreate" parameterType="SubType"> INSERT INTO subtype(title,tid) VALUES(#{title},#{type.tid}) </insert> <select id="findById" parameterType="Integer" resultMap="SubTypeResultMap"> 注意一下 SELECT stid,title,tid FROM subtype WHERE stid=#{stid} </select> <select id="findByType" parameterType="Integer" resultMap="SubTypeResultMap"> SELECT stid,title,tid FROM subtype WHERE tid=#{tid} </select> </mapper>
多对多数据映射(重难点)
♥MyBatis没有所谓的多对多的映射支持,使用的是一对多的概念来实现多对多的应用。
使用角色和权限的例子
创建 Role.java Groups.java RoleGroupsLink.java
public class RoleGroupsLink implements Serializable { private Role role; private Groups groups; }
Role.xml
<mapper namespace="ycit.sth.vo.mapping.RoleNS"> <resultMap id="RoleResultMap" type="Role"> <id property="rid" column="rid"></id> <result property="title" column="title"></result> <collection property="allGroups" javaType="java.util.List" ofType="Groups" resultMap="ycit.sth.vo.mapping.GroupsNS.GroupsResultMap"></collection> 灰色可不写 </resultMap> <!-- 角色增加要有生成的id取得,用于关系表的维护--> <insert id="doCreate" parameterType="Role" keyProperty="rid" useGeneratedKeys="true"> INSERT INTO role(title) VALUES(#{title}) </insert> <insert id="doCreateRoleGroups" parameterType="RoleGroupsLink"> INSERT INTO role_groups(rid,gid) VALUES(#{role.rid},#{groups.gid}) </insert> <update id="doUpdate" parameterType="Role"> UPDATE role SET title=#{title} WHERE rid=#{rid} </update> <delete id="doRemoveRoleGroups" parameterType="int"> DELETE FROM role_groups WHERE rid=#{rid} </delete> </mapper>
Groups.xml
<mapper namespace="ycit.sth.vo.mapping.GroupsNS"> <resultMap id="GroupsResultMap" type="Groups"> <id property="gid" column="gid"></id> <result property="title" column="title"></result> <collection property="allRoles" javaType="java.util.List" ofType="Role"></collection> </resultMap> <select id="findAllByRole" parameterType="int" resultMap="GroupsResultMap"> SELECT gid,title FROM `groups` WHERE gid IN ( SELECT gid FROM role_groups WHERE rid=#{rid}) </select> </mapper>
【注】
①role数据增加时,必须设置好role_groups表的数据
public class TestRoleAdd { public static void main(String[] args) { int gids[]=new int[]{1,2,4}; Role role=new Role(); role.setTitle("sth"); //先保存角色数据,保存之后取得角色编号,才可以向role_groups表中添加数据 if (MyBatisSessionFactory.getSession().insert("ycit.sth.vo.mapping.RoleNS.doCreate",role)>0){ int rid=role.getRid(); for (int i=0;i<gids.length;i++){ RoleGroupsLink vo=new RoleGroupsLink(); Groups groups=new Groups(); groups.setGid(gids[i]); vo.setRole(role); vo.setGroups(groups); System.out.println(MyBatisSessionFactory.getSession().insert("ycit.sth.vo.mapping.RoleNS.doCreateRoleGroups",vo)); } } MyBatisSessionFactory.getSession().commit(); MyBatisSessionFactory.getSession().close(); } }
②role数据修改的时候,需要先删除role_groups表后对应数据,然后重新添加
public class TestRoleEdit { public static void main(String[] args) { int gids[]=new int[]{3,4}; Role role=new Role(); role.setRid(3); role.setTitle("沙天慧"); if (MyBatisSessionFactory.getSession().update("ycit.sth.vo.mapping.RoleNS.doUpdate",role)>0){ if (MyBatisSessionFactory.getSession().delete("ycit.sth.vo.mapping.RoleNS.doRemoveRoleGroups",role.getRid())>0){ for (int i=0;i<gids.length;i++){ RoleGroupsLink vo=new RoleGroupsLink(); Groups groups=new Groups(); groups.setGid(gids[i]); vo.setRole(role); vo.setGroups(groups); System.out.println(MyBatisSessionFactory.getSession().insert("ycit.sth.vo.mapping.RoleNS.doCreateRoleGroups",vo)); } } } MyBatisSessionFactory.getSession().commit(); MyBatisSessionFactory.getSession().close(); } }
③role数据查询的时候可以查询出所有的权限组数据
public class TestRoleSelect { public static void main(String[] args) { List<Groups> all= MyBatisSessionFactory.getSession().selectList("ycit.sth.vo.mapping.GroupsNS.findAllByRole",3); System.out.println(all); MyBatisSessionFactory.getSession().commit(); MyBatisSessionFactory.getSession().close(); } }
SSM基础整合
♥①创建数据库,创建message表
②创建项目,配置好开发包,配置文件(web.xml,applicationContext.xml,mybatis.cfg.xml,database.properties,日志)
web.xml 添加监听器启动Spring容器,通过contextConfigLocation加载配置文件
③编写vo类,编写映射文件Message.xml
<mapper namespace="ycit.sth.vo.mapping.MessageNS"> <resultMap id="MessageResultMap" type="Message"> <id property="mid" column="mid"></id> <result property="title" column="title"></result> <result property="pubdate" column="pubdate"></result> <result property="content" column="content"></result> </resultMap> <insert id="doCreate" parameterType="Message"> INSERT INTO message(title,pubdate,content) VALUES (#{title},#{pubdate},#{content}) </insert> <select id="findAllSplit" parameterType="java.util.Map" resultMap="MessageResultMap"> SELECT mid,title,pubdate,content FROM message <where> <if test="keyword != null"> ${column} LIKE #{keyword} </if> </where> ORDER BY pubdate DESC LIMIT #{start},#{lineSize} </select> </mapper>
④数据层DAO编写及实现子类
public interface IMessageDAO { public boolean doCreate(Message vo) throws Exception; public List<Message> findAllSplit(String column,String keyword,Integer currentPage,Integer lineSize) throws Exception; }
@Component public class MessageDAOImpl implements IMessageDAO { @Resource private SqlSessionFactory sessionFactory; @Override public boolean doCreate(Message vo) throws Exception { return this.sessionFactory.openSession().insert("ycit.sth.vo.mapping.MessageNS.doCreate",vo)>0; } @Override public List<Message> findAllSplit(String column, String keyword, Integer currentPage, Integer lineSize) throws Exception { Map<String,Object> map=new HashMap<String,Object>(); map.put("column",column);if(keyword!=null){ map.put("keyword","%"+keyword+"%"); } map.put("start",(currentPage-1)*lineSize); map.put("lineSize",lineSize); return this.sessionFactory.openSession().selectList("ycit.sth.vo.mapping.MessageNS.findAllSplit",map); } }
【注】由于数据层比较简单,也可以去数据层,直接放在业务层
⑤编写业务层Service及其实现子类
public interface IMessageService { public boolean insert(Message vo) throws Exception; public List<Message> list(String column,String keyword,int currentPage,int lineSize) throws Exception; }
@Service public class MessageServiceImpl implements IMessageService { @Resource private IMessageDAO messageDAO; @Override public boolean insert(Message vo) throws Exception { return messageDAO.doCreate(vo); } @Override public List<Message> list(String column, String keyword, int currentPage, int lineSize) throws Exception { return messageDAO.findAllSplit(column,keyword,currentPage,lineSize); } }
⑥编写控制层action
@Controller @RequestMapping("/pages/message/*") public class MessageAction { @Resource private IMessageService messageService; @RequestMapping("insert") public ModelAndView insert(Message vo){ try { System.out.println(this.messageService.insert(vo)); } catch (Exception e) { e.printStackTrace(); } return null; } @RequestMapping("list") public ModelAndView list(String col,String kw,int cp,int ls){ try { System.out.println(this.messageService.list(col,kw,cp,ls)); } catch (Exception e) { e.printStackTrace(); } return null; } @InitBinder public void initBinder(WebDataBinder binder){//进行web数据的转换绑定 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); //注册一个专门的日期转换器的操作类,并且允许输入的数据为空 binder.registerCustomEditor(Date.class,new CustomDateEditor(sdf,true)); } }
【注】对于日期必须添加转换器
⑦编写显示层,我们通过地址来进行测试
http://localhost:8080/SSMProject_war_exploded/pages/message/insert.action?title=hello&pubdate=1999-07-21&content=未来可期
http://localhost:8080/SSMProject_war_exploded/pages/message/list.action?col=title&kw=hello&cp=1&ls=5

浙公网安备 33010602011771号