MVC框架——学生信息管理系统(多表,多事务如何处理,一个用户如何共用一个Connection连接)
16lz
2021-01-22
源代码代码
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;4、servlet层,与前台的交互层
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);
}
}
}
}
}
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" onclick="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>
更多相关文章
- mysql事务的默认隔离级别
- mysql学习--1.事务
- 求问vs窗体应用程序用gridview连接mysql未能获取数据库对象的列
- MySql日志与事务的隔离级别
- mysql常识以及存储引擎,锁和事务
- MySQL中一些查看事务和锁情况的常用语句
- javascript判断数组和对象中是否存在某元素
- 如何将对象作为参数传播给函数?
- RangeError:在Node.js中调试/记录/检查对象时超过了最大调用堆栈