MVC框架——学生信息管理系统(多表,多事务如何处理,一个用户如何共用一个Connection连接)




源代码代码

1、domain值对象,因为和book表有联系,所有加上List<Book>

Stud.java

package cn.hncu.domain;

import java.util.ArrayList;
import java.util.List;

public class Stud {
    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }
    private String uuid;
    private String name;
    private Integer age;
    //建立联系
    private List<Book> books=new ArrayList<Book>();//利用这种,在servlet中就没有必要导入两个对象了
    public String getUuid() {
        return uuid;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Stud() {
        super();
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Stud other = (Stud) obj;
        if (uuid == null) {
            if (other.uuid != null)
                return false;
        } else if (!uuid.equals(other.uuid))
            return false;
        return true;
    }
    
    
    
    
}

Book.java    stud对象为外键

package cn.hncu.domain;

import java.util.ArrayList;
import java.util.List;

public class Stud {
	public List<Book> getBooks() {
		return books;
	}

	public void setBooks(List<Book> books) {
		this.books = books;
	}

	public void setUuid(String uuid) {
		this.uuid = uuid;
	}
	private String uuid;
	private String name;
	private Integer age;
	//建立联系
	private List<Book> books=new ArrayList<Book>();//利用这种,在servlet中就没有必要导入两个对象了
	public String getUuid() {
		return uuid;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Stud() {
		super();
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Stud other = (Stud) obj;
		if (uuid == null) {
			if (other.uuid != null)
				return false;
		} else if (!uuid.equals(other.uuid))
			return false;
		return true;
	}
	
	
	
	
}

2、DAO层代码

StudDDAO.java

package cn.hncu.stud.dao;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import cn.hncu.domain.Stud;

public interface StudDAO {
	public abstract List<Map<String, String>> query() throws SQLException;
	public abstract void save(Stud stud) throws SQLException;
}

StudDAOJdbc.java

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.Stud;
import cn.hncu.pubs.ConUtil;

public class StudDAOImpl implements StudDAO{

	@Override
	public List<Map<String, String>> query() throws SQLException {
		List<Map<String, String>> list=new ArrayList<Map<String,String>>();
		Connection con=ConUtil.getCon();
		Statement st=con.createStatement();
		String sql="select student.uuid,student.name,student.age,book.name as bookname,book.price " +
				"from student left join book on student.uuid=book.studid";
		ResultSet rs=st.executeQuery(sql);
		while(rs.next()){
			Map<String, String> map=new HashMap<String, String>();
			map.put("uuid" , rs.getString("uuid"));
			map.put("name", rs.getString("name"));
			map.put("age", rs.getString("age"));
			map.put("bookname",  rs.getString("bookname"));
			map.put("price",  rs.getString("price"));
			list.add(map);
		}
		return list;
	}

	@Override
	public void save(Stud stud) throws SQLException {
		Connection con=ConUtil.getCon();
		String sql="insert into student(uuid,name,age) values(?,?,?)";
		PreparedStatement pst;
		pst = con.prepareStatement(sql);
		String uuid=UUID.randomUUID().toString().replaceAll("-", "");
		pst.setString(1,uuid);
		pst.setString(2, stud.getName());
		pst.setInt(3, stud.getAge());
		pst.execute();
		stud.setUuid(uuid);//设置uuid方便后面book设置外键
		//			con.close();//关不关都一样,因为设置了代理
	}

}

BookDAO.java

package cn.hncu.stud.dao;

import java.sql.SQLException;
import java.util.List;

import cn.hncu.domain.Book;

public interface BookDAO {
	public void save(List<Book> books) throws SQLException;
}

BookDAOJdbc.java

package cn.hncu.stud.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import cn.hncu.domain.Book;
import cn.hncu.pubs.ConUtil;

public class BookDAOJdbc implements BookDAO {
	
	@Override
	public void save(List<Book> books) throws SQLException {
		Connection con=ConUtil.getCon();
			String sql="insert into book(name,price,studid) values(?,?,?)";
			PreparedStatement pst=con.prepareStatement(sql);
			for (Book book:books) {
				pst.setString(1, book.getName());
				if(book.getPrice()!=null&&!book.getPrice().isNaN()&&book.getPrice()>1/1e6){
					pst.setDouble(2, book.getPrice());
				}else{
					pst.setDouble(2, 0);
				}
				
				pst.setString(3, book.getStud().getUuid());
//				pst.execute();//不能用这个语句,因为只会执行一次而且是第一次设置值的sql代码
				pst.addBatch();
			}
			pst.executeBatch();
	}

	
}

3、service层,处理事务很重要的一层,数据交互的层,最难设计的一层,我们在这层设置了事务,并把两个表进行了整合

IStudService.java

package cn.hncu.stud.service;

import java.util.List;
import java.util.Map;

import cn.hncu.domain.Stud;

public interface IStudService {
	public abstract List<Map<String, String>> query();
	public abstract void save(Stud stud);
}

ServiceStud.java

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.pubs.ConUtil;
import cn.hncu.stud.dao.BookDAO;
import cn.hncu.stud.dao.BookDAOJdbc;
import cn.hncu.stud.dao.StudDAO;
import cn.hncu.stud.dao.StudDAOImpl;

public class StudService implements IStudService {
	private StudDAO stuDao=new StudDAOImpl();
	private BookDAO booDao=new BookDAOJdbc();
	@Override
	public List<Map<String, String>> query() {
		try {
			return stuDao.query();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void save(Stud stud) {
		Connection con=null;
		try {
			con=ConUtil.getCon();
			con.setAutoCommit(false);//在逻辑层设置事务
			stuDao.save(stud); 
			booDao.save(stud.getBooks());
			con.commit();
		} catch (SQLException e) {
			try {
				con.rollback();
				System.out.println("事务回滚");
			} catch (SQLException e1) {
				throw new RuntimeException("事务回滚失败", e1);
			}//回滚
			e.printStackTrace();
		}finally{
			if(con!=null){
				try {
					con.setAutoCommit(true);
					con.close();
				} catch (SQLException e) {
					throw new RuntimeException("连接关闭失败", e);
				}
			}
		}
	}

}
4、servlet层,与前台的交互层

Stud.servlet :利用了Spring框架特点,封装了javaBean对象

package cn.hncu.stud;

import java.io.IOException;
import java.io.PrintWriter;
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.StudService;

public class StudServlet extends HttpServlet {
	private IStudService service=new StudService();
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

		public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/html;charset=utf-8");
		request.setCharacterEncoding("utf-8");
		String cmd=request.getParameter("cmd");
		if("query".equals(cmd)){
			query(request,response);
		}else if("save".equals(cmd)){
			save(request,response);
		}
		
	}
		private void query(HttpServletRequest request,
				HttpServletResponse response) throws ServletException, IOException {
			List<Map<String, String>> studs=service.query();
			request.setAttribute("studs", studs);
			request.getRequestDispatcher("/jsps/show.jsp").forward(request, response);
		}

		private void save(HttpServletRequest request,
				HttpServletResponse response) throws ServletException, IOException {
			String name=request.getParameter("name");
			String strAge=request.getParameter("age");
			if(name==null||name.trim().length()<=0||strAge==null&&strAge.trim().length()<=0){
				request.getRequestDispatcher("/index.jsp").forward(request, response);
				return;
			}
			int age=0;
			try {
				age = Integer.parseInt(strAge);
			} catch (Exception e) {
				request.getRequestDispatcher("/index.jsp").forward(request, response);
				return;
			}
			Stud stud=new Stud();
			stud.setAge(age);
			stud.setName(name);
			//收集图书参数
			String booknames[]=request.getParameterValues("booknames");
			String bookprices[]=request.getParameterValues("bookprices");
			if(booknames!=null&&booknames.length>0){
				for(int i=0;i<booknames.length;i++){
					Book book=new Book();
					book.setStud(stud);
					if(booknames[i]==null&&booknames[i].trim().length()==0){
						continue;	
					}
					book.setName(booknames[i]);
					if(bookprices[i]!=null&&bookprices[i].trim().length()>0){
						try {
							Double price=Double.parseDouble(bookprices[i]);
							book.setPrice(price);
						} catch (NumberFormatException e) {
							//出错了就不设置
						}
						//继续封装stud----为stud中的books属性赋值--一方中的集合
					}
					stud.getBooks().add(book);
				}
			}
			service.save(stud);
			query(request, response);
		}

		

}

5、工具类,对项目进行支持

ConUtil:Connect连接对象,利用了,配置文件读取,连接池,线程同步,锁,动态代理等技术,保证同一用户拿到同一对象,便于处理事务

package cn.hncu.pubs;

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 ConUtil {
	private static  ThreadLocal<Connection> tl=new ThreadLocal<Connection>(); //引入ThreadLocal来操纵同一个con对象,防止事物提交不一致的情况
	private static List<Connection> list=new ArrayList<Connection>();//con连接池
	private  static  final String FILE_NAME="jdbc.properities";
	private static  final int NUM=3;
	static{
		Properties p=new Properties();
		try {
			p.load(ConUtil.class.getClassLoader().getResourceAsStream(FILE_NAME));//用配置文件加载
			String user=p.getProperty("username");
			String url=p.getProperty("url");
			String password=p.getProperty("password");
			String driver=p.getProperty("driver");
			Class.forName(driver);
			for(int i=0;i<NUM;i++){
				final Connection con=DriverManager.getConnection(url, user, password);
				Object objCon=Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Connection.class}, new InvocationHandler() {

					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						if(method.getName().equals("close")){
							synchronized (ConUtil.class) {
								list.add((Connection) proxy);
								tl.set(null);//设为空,不能少,防止不同用户拿到同一个con
								ConUtil.class.notify();
							}
							return null;
						}
						return method.invoke(con, args);
					}
				});
				list.add((Connection)objCon);
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	synchronized public static  Connection getCon(){
		Connection con=tl.get();//从ThreadLocal中拿到一个con
		if(con==null){
			if(list.size()<=0){
				try {
					ConUtil.class.wait();
//					tl.set(getCon());//不能放在这里,因为第一次拿不到
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			con=list.remove(0);
			tl.set(con);//吧con放入ThreadLocal中
		}
		return con;
	}
	public static void main(String[] args) {
		System.out.println(getCon());
	}
}

jdbc.properities,配置文件(当中src目录下)

##MySQL
driver=com.mysql.jdbc.Driver
url=jdbc\:mysql\://127.0.0.1:3306/sstud?useUnicode\=true&characterEncoding\=utf-8
username=root
password=1234

##Oracle
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:orcl
#username=scott
#password=tiger

6、前台文件

index.jsp

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <script type="text/javascript">
     	var count =1;
    	function addBook() {
			var div=document.getElementById("div");
			div.style.width="220px";
			var fieldset=document.createElement("fieldset");
			var legend=document.createElement("legend");
			legend.innerHTML="图书"+count++;
			fieldset.appendChild(legend);
						fieldset.innerHTML+="书名:<input type='text' name='booknames'/>";
			fieldset.innerHTML+="价格:<input type='text' name='bookprices'/>";
			div.appendChild(fieldset);
		}
    </script>
    <title>MVC2</title>
  </head>
  <body>
    <a href="<c:url value='/StudServlet?cmd=query'></c:url>">查看学生信息</a><hr/>
    <form action="<c:url value='/StudServlet?cmd=save'/>" method="post">
    	姓名:<input type="text" name="name"/><br/>
    	年龄:<input type="text" name="age"/><br/>
    	<input type="button" οnclick="addBook()" value="添加图书"><br/>
    	<div id="div">
    		
    	</div><br/>
    	<input type="submit" value="注册">
    </form>
  </body>
</html>

show.jsp(el表达式,c标签)

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    
  </head>
  
  <body>
    	<caption>学生信息表</caption>
    <table border="1px">
    	<c:if test="${!empty studs }" var="boo">
    		<tr><th>id</th><th>姓名</th><th>年龄</th><th>图书名</th><th>价格</th></tr>
    		<c:forEach items="${studs}" var="stud">
    		<tr><td><c:out value="${stud.uuid}" /></td>
    			<td><c:out value="${stud.name}" /></td>
    			<td><c:out value="${stud.age}" /></td>
    			<td><c:out value="${stud.bookname}" /></td>
    			<td><c:out value="${stud.price}" /></td>
    		</tr>
    		</c:forEach>
    	</c:if>
    </table>
    	<c:if test="${!boo}">
    	<font color="red">没有相关学生信息</font>
    	</c:if>
  </body>
</html>







  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值