Hibernate学习-在线书城后台管理系统的设计
写在前面:小编经历了昨天一晚上加今天一整天的“不吃不喝(夸张点…总之就是把时间全分享给TA了)”终于把程序的问题全部解决了,小编现在的心情十分的开森,开森,开森,Happy,话不多说,直接进入正题:
------------------------------------------------------------我是一条帅气的分割线---------------------------------------------------
在线书城后台管理设计:
------------------------------------------------------------我是一条帅气的分割线------------------------------------------------------
思路分析:
1.使用的技术:MVC+Hibernate
2.首先用户进入sign-in.jsp,然后成功登陆后进入LoginServelt进行页面跳转,跳转到BooksListServlet中,然后在这个Servlet中进行页面跳转,跳转到all-books.jsp页面,通过taglib标签进行读取attribute中的数据的值
3.当用户进行删除的操作的时候,进入DeleteBooksServlet,成功删除后返回到BooksListServlet中进行页面跳转
3.当用户进行添加数据的时候,特别需要注意这一点,由于我们的isbn不是自动增长的,所以我们需要设置主键策略为assigned,而不是native,添加的时候进入add-books.jsp,表单的action对象为AddBooksServlet,当用户成功添加数据后,将页面跳转到BooksListServlet中,通过它进行页面的跳转
4.当用户进行更新数据的时候,首先需要通过QueryBooksByIdServlet<url传值>进行查询数据,并且返回到update-books.jsp,然后通过taglib进行数据读取,由于技术有限,需要对里面可以修改的数据修改,否则会出现错误,错误将导致你所在数据库的字段为null,这个因素源于更新的时候使用了seesion api,这个因素的主要是在于它的“主键”,更新结束后页面跳转到UpdateBooksServlet中,经过处理后将页面跳转到BooksListServlet
5.关于主键生成策略:
native: 会根据底层数据库的能力,从identity、sequence、hilo中选择一个,灵活性更强,但此时,如果选择sequence或者hilo,则所 有的表的主键都会从Hibernate默认的sequence或者hilo表中取。并且,有的数据库对于默认情况主键生成测试的支持,效率并不是很高
对于 oracle 采用 Sequence 方式,对于MySQL 和 SQL Server 采用identity(自增主键生成机制),native就是将主键的生成工作交由数据库完成,hibernate不管(很常用)
assigned:
由应用程序负责生成主键标识符,往往使用在数据库中没有代理主键,使用的主键与业务相关的情况,如:
这种主键的生成方式不建议使用,在数据库表设计时就应该使用代理主键(surrogate key),不应使用自然主键(natural key具有业务含义),在没有指定标签时,默认就是assigned主键的生成方式
在插入数据的时候主键由用户自己添加,hibernate也不管
ps:Hibernate所有主键策略解析:http://blog.csdn.net/caiwenfeng_for_23/article/details/43644573
------------------------------------------------------------我是一条帅气的分割线--------------------------------------------------------
关键代码:
1.数据库操作类(含有数据库的CURD操作)
package org.monster.impl; import java.util.ArrayList; import java.util.List; import org.hibernate.FlushMode; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.monster.dao.HibernateSessionFactory; import org.monster.dao.IBooksDao; import org.monster.entity.Books; /** * 书籍数据库操作实现类 */ public class BooksDaoImpl implements IBooksDao { /** * 取得书籍分页信息,这个分页是个模板,对所有的数据库都一样 * @param pageSize 每个分页的记录数 * @param pageNum 当前要获取分页页码 * @return */ @SuppressWarnings("unchecked") //这句话去掉不匹配的提示 public List<Books> getBooksPageList(int pageSize, int pageNum){ List<Books> list = new ArrayList<Books>(); Session session = HibernateSessionFactory.getSession(); try{ String hql = "from Books order by id desc"; //hql是从对象中进行查询,使用Books而不是表Books Query q = session.createQuery(hql); q.setFirstResult((pageNum-1)*pageSize); //过滤前面的pageNum-1页的数据 q.setMaxResults(pageSize); //取出当前页的数据来 list = q.list(); }catch(Exception ex){ ex.printStackTrace(); }finally{ session.close(); } return list; } /** * 取得书籍对象信息 * @param id * @return Books */ public Books getBooksItem(String id){ Books item = null; Session session = HibernateSessionFactory.getSession(); try{ String hql = "from Books where id=?"; //hql是从对象中进行查询,使用Books而不是表Books Query q = session.createQuery(hql); q.setString(0, id); item = (Books) q.uniqueResult(); }catch(Exception ex){ ex.printStackTrace(); }finally{ session.close(); } return item; } /** * 添加书籍信息 * 需要事务处理 */ public void addBooks(Books item){ Session session = HibernateSessionFactory.getSession(); Transaction tran = session.beginTransaction(); //开启事务 try{ session.save(item); tran.commit(); //执行事务 }catch(Exception ex){ tran.rollback(); //回滚事务 ex.printStackTrace(); }finally{ session.close(); } } /** * 修改书籍信息[由于图书的字段值很多,管理员也许只需要添加部分字段,所以可以通过session接口进行操作] * @param item 要修改的对象 * @return */ public void editBooks(Books item){ Session session = HibernateSessionFactory.getSession(); Transaction tran = session.beginTransaction(); //开启事务 try{ session.update(item); tran.commit(); }catch(Exception ex){ tran.rollback(); ex.printStackTrace(); }finally{ session.close(); } } /** * 删除书籍信息 * @param id * @return iRow */ public int delBooks(int id){ int iRow =0 ; //影响的行数 Session session = HibernateSessionFactory.getSession(); Transaction tran = session.beginTransaction(); //开启事务 try{ String hql = "delete from Books where id=?"; //hql是从对象中进行查询,使用Books而不是表Books Query q = session.createQuery(hql); q.setInteger(0,id); iRow = q.executeUpdate(); tran.commit(); //执行事务 }catch(Exception ex){ tran.rollback(); //回滚事务 ex.printStackTrace(); }finally{ session.close(); } return iRow; } }
ps:上述代码经单元测试全部通过
2. 单元测试的代码:
package org.monster.test; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import org.monster.dao.IBooksDao; import org.monster.entity.Books; import org.monster.impl.BooksDaoImpl; import junit.framework.TestCase; public class TestCURD extends TestCase { public void testGetBooksPageList() { IBooksDao dao=new BooksDaoImpl(); List<Books> bookList=dao.getBooksPageList(20, 1); //得到图书列表 for(int i=0;i<bookList.size();i++){ Books book=bookList.get(i); System.err.println("出版社"+book.getPublisherName()); } } public void testGetBooksItem() { IBooksDao dao=new BooksDaoImpl(); Books book=dao.getBooksItem("0130284190"); System.out.println("数据"+book.getPublisherName()); } public void testAddBooks() { /**创建Books对象并且赋值**/ Books book=new Books(); book.setIsbn("010102023"); book.setTitle("亲,我怎么又成炮灰了"); book.setPrice(250.0); book.setPubDt(new Date()); book.setPublisherName("滨州出版社"); /**进行添加操作**/ IBooksDao dao=new BooksDaoImpl(); dao.addBooks(book); } private String getData() { // 得到时间的方法 Date date=new Date(); SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:SS;mm"); String str=format.format(date); return str; } public void testEditBooks() { IBooksDao dao=new BooksDaoImpl(); Books book=new Books(); book.setIsbn("0130829288"); book.setPublisherName("临沂出版社"); book.setPrice(120.00); book.setTitle("我是书名,我好伤心- -!!"); book.setPubDt(new Date()); dao.editBooks(book); } public void testDelBooks() { IBooksDao dao=new BooksDaoImpl(); int i=dao.delBooks(1); System.out.println("返回行数" +i); } }
3.关于数据更新时的乱码问题解决:
request.setCharacterEncoding("utf-8"); //转码操作
4.小编觉得在在数据库的CURD操作的时候,应该注意各个servlet类间的灵活调用,因为servlet作为一个控制器,负责对各页面进行跳转并且携带数据跳转,小编觉得关于跳转时候的关键代码:
eg:以查询所有图书为例
IBooksDao dao=new BooksDaoImpl(); List<Books> bookList=dao.getBooksPageList(20, 1); //得到图书列表 request.setAttribute("BooksList", bookList); request.getRequestDispatcher("all-books.jsp").forward(request, response);
5.关于在页面中进行显示,由于我们对数据进行setAttribute操作,所有我们在页面中可以通过taglib标签进行显示
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:set var="BooksList" value="${requestScope.BooksList}"></c:set> <c:forEach items="${BooksList}" var="item"> <tr> <td>${item.isbn}</td> <td>${item.title}</td> <td>${item.price}</td> <td>${item.pubDt}</td> <td>图片收集中</td> <td>${item.publisherName}</td> <td> <!--商品信息更改和删除开始--> <a href="QueryBooksByIdServlet?isbn=${item.isbn}"><i class="icon-pencil"></i></a> <a href="DeleteBooksServlet?isbn=${item.isbn}" role="button" data-toggle="modal"><i class="icon-remove"></i></a> <!--商品信息更改和删除结束--> </td> </tr> </c:forEach>
6.源码分享