欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java学生信息管理系统设计(2)

程序员文章站 2024-03-11 11:45:43
本例的学生信息添加进入数据库的事务(可以提交事务,事务回滚,用本地线程完善) 主页面index.jsp <%@ page language="java...

本例的学生信息添加进入数据库的事务(可以提交事务,事务回滚,用本地线程完善)

java学生信息管理系统设计(2)

主页面index.jsp

<%@ page language="java" import="java.util.*" pageencoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
 <head>

 <title>学生信息管理</title>
 </head>

 <body>
 <a href='<c:url value="/query"/>?cmd=query'>查看学生信息</a>
 <br><br>
 <!-- 
 <a href="<c:url value='/studservlet?cmd=save' />">学生信息添加</a>
 -->
 <h2>学生信息添加</h2>
 <form action='<c:url value="/query"/>?cmd=add' method="post">
 姓名:<input type="text" name="name"/><br><br>

 <fieldset style="border: solid;border-color: red;width: 250px;">
  <legend>图书1</legend>
  书名:<input type="text" name="book"/><br><br>
  价格:<input type="text" name="price"/>
 </fieldset>
 <br>
 <fieldset style="border: solid;border-color:green;width: 250px;">
  <legend>图书2</legend>
  书名:<input type="text" name="book"/><br><br>
  价格:<input type="text" name="price"/>
 </fieldset>
 <br><br>
 <input type="submit" value="提交"/><br><br>
 </form>
 </body>
</html>

工具包

获取数据库连接的工具connutils5.java

package cn.hncu.utils;

import java.lang.reflect.invocationhandler;
import java.lang.reflect.method;
import java.lang.reflect.proxy;
import java.sql.connection;
import java.sql.drivermanager;
import java.util.arraylist;
import java.util.list;
import java.util.properties;

public class connutils5 {

 //本地线程管理对象,用于实现: 同一个线程获取的连接是同一个
 private static threadlocal< connection> t=new threadlocal<connection>();
 private final static list<connection> pool=new arraylist<connection>();
 private static int size;//由资源文件读取
 private connutils5(){

 }
 static{
 properties p=new properties();
 try {
  //下面这种方式在纯java项目中可以读取到classpath下的资源文件,但无法读取javaee项目的。因为tomcat把系统的默认类加载器改了
  //p.load( classloader.getsystemclassloader().getsystemresourceasstream("jdbc.properties"));
//  p.load(classloader.getsystemresourceasstream("jdbc.properties"));

  //读取web项目的classpath下的资源文件,用这个可以
  p.load(connutils3.class.getclassloader().getresourceasstream("jdbc.properties"));
  string driver=p.getproperty("driver");
  string url=p.getproperty("url");
  string name=p.getproperty("username");
  string pwd=p.getproperty("password");
  string ssize=p.getproperty("size");
  size=integer.parseint(ssize);
  class.forname(driver);
  for(int i=0;i<size;i++){
  final connection con=drivermanager.getconnection(url,name,pwd);
  system.out.println("con=="+con);
  //更改conn.close()方法
  //用代理模式生成一个增强版的conn对象,把它的close()方法拦截更改掉
  object ncon=proxy.newproxyinstance(
   connutils3.class.getclassloader(), 
   // conn.getclass().getinterfaces(), 
   //后面这种方式不行,应该是驱动中的实现类和我们当前程序不在同一空间(类加载器不同) 
   new class[]{connection.class}, 
   new invocationhandler() {
    @override
    public object invoke(object proxy, method method, object[] args)
     throws throwable {
    if(method.getname().equals("close")){
     system.out.println("还回一个链接:"+(connection)proxy);
     pool.add((connection)proxy);
     return null;
    }
    return method.invoke(con, args);
    }
  });
  pool.add((connection)ncon);
  }
 } catch (exception e) {
  e.printstacktrace();
 }
 }
 public static synchronized connection getconnection(){
 //先从t中拿,如果有就拿出去,如果没有再到池中拿且把该对象放到t中
 connection con=t.get();
 if(con==null){

  if(pool.size()<=0){
  system.out.println("池中连接没有了...");
  try {
   thread.sleep(1000);
  } catch (interruptedexception e) {
   e.printstacktrace();
  }
  return getconnection();
  }
  con=pool.remove(0);
  t.set(con);//放到t中
 }

 return con;//拿一个移一个
 }


}

代理

package cn.hncu.utils;

import java.lang.reflect.invocationhandler;
import java.lang.reflect.method;
import java.lang.reflect.proxy;
import java.sql.connection;
import java.sql.sqlexception;

public class txproxy implements invocationhandler {

 private object srcobj=null;

 private txproxy(object srcobj) {
 this.srcobj = srcobj;
 }


 public static object getproxy(object srcobj){
 system.out.println("srcobj:"+srcobj);
 object newobj=proxy.newproxyinstance(
  txproxy.class.getclassloader(), 
  srcobj.getclass().getinterfaces(), 
  new txproxy(srcobj));
 system.out.println("newobj:"+newobj);
 return newobj;
 }

 @override
 public object invoke(object proxy, method method, object[] args)
  throws throwable {
 connection con=null;
 object returnobj=null;
 try {
  con=connutils5.getconnection();
  system.out.println("invoke拿到一个链接:"+con);
  con.setautocommit(false);

  returnobj=method.invoke(srcobj, args);

  system.out.println("提交一个事务...");
  con.commit();
 } catch (exception e) {
  try {
  system.out.println("回滚一个事务...");
  con.rollback();
  } catch (sqlexception e1) {
  e1.printstacktrace();
  }
 }finally{
  try {
  con.setautocommit(true);
  con.close();
  } catch (sqlexception e) {
  e.printstacktrace();
  }
 }
 return returnobj;
 }

}

代理2:不需要强转,但是代理了所有

package cn.hncu.utils;

import java.lang.reflect.invocationhandler;
import java.lang.reflect.method;
import java.lang.reflect.proxy;
import java.sql.connection;
import java.sql.sqlexception;

public class txproxy2 implements invocationhandler {

 private object srcobj=null;

 private txproxy2(object srcobj) {
 this.srcobj = srcobj;
 }


 public static<t> t getproxy(class<t> c){
 object obj=null;
 try {
  obj = c.newinstance();
 } catch (exception e) {
  e.printstacktrace();
 }
 object newobj=proxy.newproxyinstance(
  txproxy2.class.getclassloader(), 
  c.getinterfaces(), 
  new txproxy2(obj));
 return (t) newobj;
 }

 @override
 public object invoke(object proxy, method method, object[] args)
  throws throwable {
 connection con=null;
 object returnobj=null;
 try {
  con=connutils5.getconnection();
  system.out.println("invoke拿到一个链接:"+con);
  con.setautocommit(false);

  returnobj=method.invoke(srcobj, args);

  system.out.println("提交一个事务...");
  con.commit();
 } catch (exception e) {
  try {
  system.out.println("回滚一个事务...");
  con.rollback();
  } catch (sqlexception e1) {
  e1.printstacktrace();
  }
 }finally{
  try {
  con.setautocommit(true);
  con.close();
  } catch (sqlexception e) {
  e.printstacktrace();
  }
 }
 return returnobj;
 }

}

注解

package cn.hncu.utils;

import java.lang.annotation.elementtype;
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
import java.lang.annotation.target;

@target(value=elementtype.method)
@retention(retentionpolicy.runtime)
public @interface transaction {

}

代理3:用注解实现需要事务则用事务

package cn.hncu.utils;

import java.lang.reflect.invocationhandler;
import java.lang.reflect.method;
import java.lang.reflect.proxy;
import java.sql.connection;
import java.sql.sqlexception;

public class txproxy3 implements invocationhandler {

 private object srcobj=null;

 private txproxy3(object srcobj) {
 this.srcobj = srcobj;
 }


 public static<t> t getproxy(t srcobj){
 object newobj=proxy.newproxyinstance(
  txproxy3.class.getclassloader(), 
  srcobj.getclass().getinterfaces(), 
  new txproxy3(srcobj));
 return (t) newobj;
 }

 @override
 public object invoke(object proxy, method method, object[] args)
  throws throwable {
 /* 这种方式来实现只拦截指定的方法
 if(method.getname().equals("close")){
  ...拦截
 }else{
  return method.invoke(srcobj, args);
 }
 */
 if(method.isannotationpresent(transaction.class)){

  connection con=null;
  object returnobj=null;
  try {
  con=connutils5.getconnection();
  system.out.println("invoke拿到一个链接:"+con);
  con.setautocommit(false);
  //真正的业务代码,放行
  returnobj=method.invoke(srcobj, args);

  system.out.println("提交一个事务...");
  con.commit();
  } catch (exception e) {
  try {
   system.out.println("回滚一个事务...");
   con.rollback();
  } catch (sqlexception e1) {
   e1.printstacktrace();
  }
  }finally{
  try {
   con.setautocommit(true);
   con.close();
  } catch (sqlexception e) {
   e.printstacktrace();
  }
  }
  return returnobj;
 }else{
  system.out.println("不存在事务注解,直接放行!");
  return method.invoke(srcobj, args);
 }
 }

}

资源文件jdbc.properties

##mysql
driver=com.mysql.jdbc.driver
url=jdbc:mysql://127.0.0.1:3306/hncu?useunicode=true&characterencoding=utf-8
username=root
password=1234
size=3
##oracle
#driver=oracle.jdbc.driver.oracledriver
#url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
#username=scott
#password=tiger

stud层的servlet层–queryservlet.java

package cn.hncu.stud.servlet;

import java.io.ioexception;
import java.util.list;
import java.util.map;

import javax.servlet.servletexception;
import javax.servlet.http.httpservlet;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;

import cn.hncu.domain.book;
import cn.hncu.domain.stud;
import cn.hncu.stud.service.istudservice;
import cn.hncu.stud.service.studserviceimpl;
import cn.hncu.utils.txproxy3;

public class queryservlet extends httpservlet {

 //注入
 //1.
// istudservice service=(istudservice) txproxy.getproxy(new studserviceimpl());
 //2.
// istudservice service=txproxy2.getproxy(studserviceimpl.class);
 //3.
 istudservice service=txproxy3.getproxy(new studserviceimpl());
 public void doget(httpservletrequest request, httpservletresponse response)
  throws servletexception, ioexception {

 dopost(request, response);
 }


 public void dopost(httpservletrequest request, httpservletresponse response)
  throws servletexception, ioexception {
 string cmd=request.getparameter("cmd");
 system.out.println("cmd:"+cmd);
 if("query".equals(cmd)){
  query(request, response);
 }else if("add".equals(cmd)){
  add(request, response);
 }
 }


 public void query(httpservletrequest request, httpservletresponse response)
  throws servletexception, ioexception {
 system.out.println("service:"+service);
 list<map<string, string>> studs=service.query();
 request.setattribute("studs", studs);
 request.getrequestdispatcher("/jsps/show.jsp").forward(request, response);
 }
 public void add(httpservletrequest request, httpservletresponse response)
  throws servletexception, ioexception {
 //1收集参数 2组织参数(id字段留到dao中去补)
 string name[]=request.getparametervalues("name");
 stud s=new stud();
 s.setname(name[0]);
 //图书信息
 string books[]=request.getparametervalues("book");
 //防护一下 ---价格的防护应该也要写,这里我们偷懒了
 if(books==null||books.length<=0){
  return;
 }
 string prices[]=request.getparametervalues("price");
 for(int i=0;i<books.length;i++){
  book b=new book();
  b.setname(books[i]);
  b.setprice(double.parsedouble(prices[i]));
  //※完成两个值对象的“一对多”关系的数据封装
  s.getbooks().add(b);//一方
  b.sets(s);//多方
 }
 //3调用service层
 try {
  service.save(s);
 } catch (exception e) {
  //导向失败页面
 }

 }

}

stud层的service层–
接口:

package cn.hncu.stud.service;

import java.util.list;
import java.util.map;

import cn.hncu.domain.stud;
import cn.hncu.utils.transaction;



public interface istudservice {

 public list<map<string, string>> query();

 //注意,注解只有放在接口才有用,,,,写在实现类中的方法无效(不会决定开启事务)
 @transaction
 public void save(stud stud) throws exception ;
}

实现类

package cn.hncu.stud.service;


import java.sql.connection;
import java.sql.sqlexception;
import java.util.list;
import java.util.map;

import cn.hncu.domain.stud;
import cn.hncu.stud.dao.bookdao;
import cn.hncu.stud.dao.bookjdbcdao;
import cn.hncu.stud.dao.studdao;
import cn.hncu.stud.dao.studjdbcdao;
import cn.hncu.utils.connutils5;

/*我们以后开发时通常都要采用一个dao独立操作一个表,系统中有几个实体表就写几个dao,
 * 以后框架都是这么干的,我们也要这样做,因为架构好!
 * 
 * 采用事务的场合:
 * 1、如果只有一个dao,但要执行多条sql语句且涉及增删改,则要开启事务
 * 2、如果一个service调用多个dao,通常也要开启事务。
 */
public class studserviceimpl implements istudservice {

 //注入
 studdao dao_stud=new studjdbcdao();
 bookdao dao_book=new bookjdbcdao();
 @override
 public list<map<string, string>> query() {
 return dao_stud.query();
 }
 @override
 public void save(stud stud) throws exception {
 dao_stud.save(stud);
 dao_book.save(stud.getbooks());
 }

}

stud层的dao层–
stud接口–分离式做法,一个表对应一个dao,为框架做准备

package cn.hncu.stud.dao;

import java.util.list;
import java.util.map;

import cn.hncu.domain.stud;

public interface studdao {

 public list<map<string, string>> query();
 public void save(stud stud) throws exception;
}

stud实现类

package cn.hncu.stud.dao;

import java.sql.connection;
import java.sql.preparedstatement;
import java.sql.resultset;
import java.sql.sqlexception;
import java.sql.statement;
import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.map;
import java.util.uuid;

import cn.hncu.domain.book;
import cn.hncu.domain.stud;
import cn.hncu.utils.connutils3;

public class studjdbcdao implements studdao {

 @override
 public list<map<string, string>> query() {
 list<map<string, string>> list=new arraylist<map<string,string>>();
 //一个map就是一行数据, list<map>就是整个数据表
 connection con=null;
 try {
  con=connutils3.getconnection();
  statement st=con.createstatement();
  string sql="select * from stud";
  resultset rs=st.executequery(sql);
  while(rs.next()){
  map<string,string> m=new hashmap<string, string>();
  m.put("id", (string) rs.getobject(1));
  m.put("name", (string) rs.getobject(2));
  list.add(m);
  }
  rs.close();
  st.close();
 } catch (sqlexception e) {
  e.printstacktrace();
 }finally{
  try {
  con.close();
  } catch (sqlexception e) {
  e.printstacktrace();
  }
 }


 return list;
 }

 @override
 public void save(stud stud) throws exception {
 connection con=connutils3.getconnection();
 system.out.println("拿到一个链接:"+con);
 string sql="insert into stud values(?,?)";
 string uuid=uuid.randomuuid().tostring().replace("-", "");
 preparedstatement pst=con.preparestatement(sql);
 stud.setid(uuid);//为了"多方"即book能够拿到"一方"的id,专门补的
 pst.setstring(1, uuid);
 pst.setstring(2, stud.getname());
 system.out.println("1:"+uuid+",2:"+stud.getname());
 pst.executeupdate();
// con.close();//拿到同一个con,这里就不需要关了
 }

}

book接口

package cn.hncu.stud.dao;

import java.util.list;

import cn.hncu.domain.book;

public interface bookdao {

 public void save(list<book> books) throws exception;
}

book实现类

package cn.hncu.stud.dao;

import java.sql.connection;
import java.sql.preparedstatement;
import java.util.list;

import cn.hncu.domain.book;
import cn.hncu.utils.connutils3;

public class bookjdbcdao implements bookdao {

 @override
 public void save(list<book> books) throws exception {
 connection con=connutils3.getconnection();
 system.out.println("拿到一个链接:"+con);
 string sql="insert into book(name,price,studid) values(?,?,?)";
 preparedstatement pst=con.preparestatement(sql);
 for(book b:books){
  pst.setstring(1, b.getname());
  pst.setdouble(2, b.getprice());
  pst.setobject(3, "12132312");//异常(故意给一个不存在的外键字段,以测试事务回滚)--测事务回滚
//  pst.setobject(3, b.gets().getid());
  system.out.println("1:"+b.getname()+",2:"+b.getprice()+",3:"+b.gets().getid());
  pst.addbatch();//添加到批处理
 }
 pst.executebatch();//执行批处理

// con.close();//这里拿到同一个con,这里不需要关

 }

}

值对象
stud对象

package cn.hncu.domain;

import java.util.arraylist;
import java.util.list;
/*
 * 一对多中的 “一”方 值对象的建法
 */
public class stud {

 private string id;
 private string name;
 //※专为“多”方添加一个集合---体现多表中的“一对多关系”
 private list<book> books=new arraylist<book>();//注意,该集合要在构造时或之前就new出来。
 public string getid() {
 return id;
 }
 public void setid(string id) {
 this.id = id;
 }
 public string getname() {
 return name;
 }
 public void setname(string name) {
 this.name = name;
 }



 public list<book> getbooks() {
 return books;
 }
 public void setbooks(list<book> books) {
 this.books = books;
 }
 @override
 public string tostring() {
 return "id=" + id + "," + name + "," + books;
 }

}

book对象

package cn.hncu.domain;
/*
 * 一对多中的 “多”方 值对象的建法
 */
public class book {

 private integer id;
 //基本数据类型全部用包装类的声明,为以后使用框架做技术准备---包装类能够兼容框架(因为一般框架都会使用类反射)
 private string name;
 private double price;
 //※专为“一”方添加一个对象类型的变量(注意,不用studid)---体现多表中的“一对多关系”
 private stud s;//设置主人
 //private string studid;//★★不要这样设
 public integer getid() {
 return id;
 }
 public void setid(integer id) {
 this.id = id;
 }
 public string getname() {
 return name;
 }
 public void setname(string name) {
 this.name = name;
 }
 public double getprice() {
 return price;
 }
 public void setprice(double price) {
 this.price = price;
 }
 public stud gets() {
 return s;
 }
 public void sets(stud s) {
 this.s = s;
 }
 /*
 * 多表关联时的tostring()方法要注意一个陷阱,就是一方输出另一方,同时另一方又反过来输出前一方,形成无穷递归!
 */
 @override
 public string tostring() {
 return "id=" + id + "," + name + "," + price;//这里不能输出stud对象,否则无穷递归
 }

}

显示学生信息页面jsps/show.jsp

<%@ page language="java" import="java.util.*" pageencoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
 <head>

 <title>学生信息管理</title>
 </head>

 <body>
 <h2>学生信息</h2>
 <c:foreach items="${studs}" var="x">
 ${x.id},${x.name}<br/>
 </c:foreach>
 </body>
</html>

效果图:

java学生信息管理系统设计(2)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。