Spring練習:JDBC模板和事務回滾
SSH框架是每個學生畢業前都必須掌握的一門技術,所以這裡就用Spring的JDBC模板和自定義異常讓事務回滾來做一個練習。主要用到的是spring和struts2框架來操作,這裡暫時沒用Hibernate來對資料進行操作。
一、練習要求。
要求寫一個使用者購買股票的專案,使用者先開戶後登陸,可以在裡面買股票和賣股票,當買股票金額超過使用者金額時就報異常讓事務回滾,使用者賣出股票時超過持有數量報異常讓事務回滾。
二、資料庫表
這裡因為沒有用到Hibernate所以不能通過配置實體類建立表,所以只能手動建立,表結構如下:
person表;
stock表
三、建立包和配置好所需的配置檔案
先匯入spring和struts2所需要用到的包,再建立配置檔案,然後我們再新建對應的Package。
四、開戶和登入
買或賣股票之前每個人都有自己的賬戶來存自己的金額和資訊,這裡先設計好jsp頁面讓使用者進行選擇是開戶還是登入。(這裡只是簡單的弄了下jsp頁面)
點選開戶就進到另一個jsp頁面來進行操作
到寫資料操作語句,這裡要先對使用者名稱進行排重下,以免重複賬戶。先到Dao層寫好介面,讓DaoImp層實現介面。
DaoImp實現介面時也要繼承下JdbcDaoSupport這樣才能對資料進行處理。
再寫Service層介面,讓ServiceImp層實現,Service層介面的方法就是Dao層介面的方法,所以為了方便集中把所以的Dao層介面方法都寫在了一個Service層接口裡面,ServiceImp層也是直接呼叫Dao層物件來實現全部方法。public class ZhuCeDaoImp extends JdbcDaoSupport implements ZhuCeDao{ @Override public boolean addUser(Person p) { System.out.println("進入開戶~~~"); //排重,如果為true就直接返回false; if(this.touser(p.getUserName())){ return false; } //如果排除為false,就好進行新增使用者,這裡我們傳實體類就可以獲取到對應的引數。 String sql = "insert into person(username,password,money) value (?,?,?)"; //直接this關鍵字呼叫繼承父類的方法來操作sql語句 int i = this.getJdbcTemplate().update(sql,p.getUserName(),p.getPassWord(),p.getMoney()); if(i!=0){ //判斷下,在後臺輸出看是否成功 System.out.println("開戶成功"); return true; }else{ System.out.println("開戶失敗"); return false; } } //使用者名稱排重 public boolean touser(String name){ System.out.println("進入排重~~~"); //查詢對應的使用者名稱 String sql = "select username from person where username=?"; List s = this.getJdbcTemplate().queryForList(sql, String.class,name); //存的是List型別,所以list不為空就是該使用者名稱已存在,反之則沒有 if(s.size()!=0){ return true; } return false; } }
Service層
當用戶填寫完form表單後點擊開戶提交就會通過struts2呼叫對應的action層,action層再呼叫Service層來對資料進行操作,要配置好spring配置檔案。public interface TestService { //使用者開戶 public boolean addUser(Person p); //使用者登入 public boolean toLogin(Person p); //買股票 public boolean tobuy(String stockName,String username,int count) throws MyException; //賣股票 public boolean tosell(String stockName,String username,int count) throws MyException; //獲取登入使用者的所以股票資訊 public List<Stock> getUser(String userName); //獲取登入使用者的總價 public double getMoney(String userName); }
public class ZhuCeKZ extends ActionSupport{
//建立實體類,通過反射可以獲取到form表單的提交資料,
//但form表單的名字必須和實體類屬性名相同,提供set,get方法,
private Person p;
public String toZhuCe(){
//spring自動建立Service物件
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
TestService ts = (TestService) ac.getBean("textS");
//呼叫開戶處理,true就跳到登入檢視,false就跳回註冊檢視重新註冊
if(ts.addUser(p)){
return "success";
}else{
return "shibai";
}
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
}
成功註冊後,就進入登入的jsp頁面。
也是先寫好Dao層介面和讓DaoImp實現,再Service層介面讓ServiceImp實現
Dao層
public interface LoginDao {
public boolean toLogin(Person p);
}
DaoImp層
public class LoginDaoImp extends JdbcDaoSupport implements LoginDao{
@Override
public boolean toLogin(Person p) {
System.out.println("進入登入~~~");
//先根據使用者名稱查下是否存在
String sql = "select * from person where username=?";
//因為Person不是基本資料型別,所以要先自定義型別下
RowMapper<Person> rowMapper = new BeanPropertyRowMapper<Person>(Person.class);
List<Person> list = this.getJdbcTemplate().query(sql, rowMapper,p.getUserName());
//存在List裡面,判斷下為空表示沒有改資料
if(list.size()!=0){
//不為空的話就讓查詢到的實體和登入的實體密碼就行判斷
if(list.get(0).getPassWord().equals(p.getPassWord())){
return true;
}
}
return false;
}
}
form表單提交跳到對應Action層,呼叫Service物件操作。
public class LoginKZ extends ActionSupport{
private Person p;
public String toLogin(){
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
TestService ts = (TestService) ac.getBean("textS");
if(ts.toLogin(p)){
//把使用者名稱存進session裡面在頁面顯示下,和後面方便資料存取
ActionContext.getContext().getSession().put("username", p.getUserName());
return "success";
}
return "shibai";
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
}
五、股票的買和賣
成功登入後就會跳到一個功能介面,用來購買股票和檢視使用者持有股。
當點選股票市場時就會進入檢視股票價格,買賣股票可以輸入對應的數量,所以用了些js來操作。
先寫好Dao層的資料操作。
Dao層介面
public interface TradeDao {
//買股票
public boolean tobuy(String stockName,String username,int count);
//賣股票
public boolean tosell(String stockName,String username,int count);
//獲取登入使用者的所以股票資訊
public List<Stock> getUser(String userName);
//獲取登入使用者的總價
public double getMoney(String userName);
}
DaoImp層
public class TradeDaoImp extends JdbcDaoSupport implements TradeDao{
//買股票處理
@Override
public boolean tobuy(String stockName, String username, int count) {
System.out.println(username+"買"+stockName+"股票數量:"+count);
//呼叫寫好的排除股票重複方法
if(this.getBuy(stockName, username)){
//重複就直接更新股票數量
String sql = "update stock set number=number+? where stockName=? and userName=?";
this.getJdbcTemplate().update(sql,count,stockName,username);
//呼叫寫好的(購買股票數量*股票價格)方法,來進行對使用者金額的加減
double money = this.zeng(count, stockName);
String sql2 = "update person set money=money-? where userName=?";
this.getJdbcTemplate().update(sql2,money,username);
System.out.println("購買股票成功");
return true;
}
//如果排重為false就是新購買,所以要新新增股票資訊進資料庫
String sql = "insert into stock(stockName,userName,number) value(?,?,?)";
int i = this.getJdbcTemplate().update(sql,stockName,username,count);
//如果成功就呼叫寫好的(購買股票數量*股票價格)方法,來進行對使用者金額的加減
if(i!=0){
double money = this.zeng(count, stockName);
String sql2 = "update person set money=money-? where userName=?";
this.getJdbcTemplate().update(sql2,money,username);
System.out.println("購買股票成功");
return true;
}
System.out.println("購買股票失敗");
return false;
}
//賣股票處理
@Override
public boolean tosell(String stockName, String username, int count) {
System.out.println(username+"賣"+stockName+"股票數量:"+count);
//呼叫寫好的方法,判斷賣出數量是否超過持有數,超過就直接返回false
int cou = this.getStock(stockName, username);
if(cou<count){
return false;
}
//呼叫排重方法,false就是沒持有改股票,true就是持有該股票
if(this.getBuy(stockName, username)){
//持有股票數量減去賣出數量
String sql = "update stock set number=number-? where stockName=? and userName=?";
this.getJdbcTemplate().update(sql,count,stockName,username);
//呼叫寫好的(購買股票數量*股票價格)方法,來進行對使用者金額的加減
double money = this.zeng(count, stockName);
String sql2 = "update person set money=money+? where userName=?";
this.getJdbcTemplate().update(sql2,money,username);
return true;
}
return false;
}
//遍歷出使用者股票數量
@Override
public List<Stock> getUser(String userName) {
System.out.println("遍歷使用者股票");
String sql = "select * from stock where userName=?";
//因為Stock不是基本資料型別,所以要先自定義型別下
RowMapper<Stock> rowMapper = new BeanPropertyRowMapper<Stock>(Stock.class);
List<Stock> list =this.getJdbcTemplate().query(sql,rowMapper,userName);
return list;
}
//獲取剩餘資產
@Override
public double getMoney(String userName) {
String sql = "select money from person where userName=?";
double money = this.getJdbcTemplate().queryForObject(sql, Double.class,userName);
return money;
}
//自定義方法
//股票排重
public boolean getBuy(String stockName, String username){
String sql = "select * from stock where stockName=?";
RowMapper<Stock> rowMapper = new BeanPropertyRowMapper<Stock>(Stock.class);
List<Stock> list = this.getJdbcTemplate().query(sql,rowMapper,stockName);
if(list.size()!=0){
for(int i=0;i<list.size();i++){
if(list.get(i).getUserName().equals(username)){
return true;
}}}
return false;
}
//判斷型別對money進行加減
public double zeng(int count,String type){
double i = 0;
//因為這裡沒存進資料庫,所以直接寫死
if(type.equals("華為")){
i = count*200;
}
if(type.equals("網易")){
i = count*300;
}
if(type.equals("三星")){
i = count*20;
}
return i;
}
//獲取已有的股票數,來判斷是否超過賣出的數量
public int getStock(String stockName,String userName){
String sql = "select number from stock where stockName=? and userName=?";
int i = this.getJdbcTemplate().queryForInt(sql, stockName,userName);
return i;
}
}
當用戶輸入數量點選買賣股票時,就會跳到對應的Action層來呼叫Service物件,ServiceImp層直接呼叫Dao層物件來操作。
public class StockKZ {
//股票名,jsp頁面傳過來
private String stockName;
//股票數量,jsp頁面傳過來
private int count;
//登入使用者持有股票
private ArrayList list;
//總價
private double money;
//定義成成員變數方便呼叫
ApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
//這裡呼叫的是代理物件
TestService ts = (TestService) ac.getBean("serviceProxy");
//買股票控制
public String toBuy(){
//使用者名稱在登入時已經存進session裡面,所以可以獲取到
String username = ActionContext.getContext().getSession().get("username").toString();
try {
if(ts.tobuy(stockName, username, count)){
return "success";
}
} catch (MyException e) {
e.printStackTrace();
}
return "shibai";
}
//賣股票控制
public String toSell(){
String username = ActionContext.getContext().getSession().get("username").toString();
try {
if(ts.tosell(stockName, username, count)){
return "success";
}
} catch (MyException e) {
e.printStackTrace();
}
return "shibai";
}
//檢視資產和持股票數量
public String getZiCang() {
String userName = ActionContext.getContext().getSession().get("username").toString();
list = (ArrayList) ts.getUser(userName);
money = ts.getMoney(userName);
return "success2";
}
//set,get
public void setStockName(String stockName) {
this.stockName = stockName;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void setList(ArrayList list) {
this.list = list;
}
public ArrayList getList() {
return list;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
這樣就可以買賣股票,在頁面上顯示登入使用者持有股票和剩餘金額
六、事務的回滾
如何讓事務回滾,這裡就要自定義異常,當有異常時就會讓事務回滾,從而讓資料沒有改變。所以我們在買賣股票時加下判斷,這裡就要到ServiceImp層操作
public class TestServiceImp implements TestService{
//開戶Dao
private ZhuCeDao zd;
//登入Dao
private LoginDao ld;
//股票操作Dao
private TradeDao td;
//使用者開戶
@Override
public boolean addUser(Person p) {
return zd.addUser(p);
}
//使用者登入
@Override
public boolean toLogin(Person p) {
return ld.toLogin(p);
}
//買股票
@Override
public boolean tobuy(String stockName, String username, int count) throws MyException {
td.tobuy(stockName, username, count);
//獲取下剩餘的資產
double money = this.getMoney(username);
//如果小於0就拋異常,讓事務回滾
if(money<0){
throw new MyException("你已經沒有錢了~~~");
}
return true;
}
//賣股票
@Override
public boolean tosell(String stockName, String username, int count) throws MyException {
//獲取下使用者的全部持有股票資訊
List list = this.getUser(username);
if(list.size()!=0){
//不為空就遍歷
for(int i=0;i<list.size();i++){
Stock stock = (Stock) list.get(i);
//匹配股票名字是否相同,相同就判斷使用者持有該股票數量
//如果小於等於0就拋異常,讓事務回滾
if(stockName.equals(stock.getStockName())&&stock.getNumber()<=0){
throw new MyException("你已經沒有該公司的股票~~~");
}
}
}
return td.tosell(stockName, username, count);
}
//登入使用者持有股票
@Override
public List<Stock> getUser(String userName){
List list = td.getUser(userName);
return list;
}
//獲取總價
@Override
public double getMoney(String userName) {
return td.getMoney(userName);
}
//set
public void setZd(ZhuCeDao zd) {
this.zd = zd;
}
public void setLd(LoginDao ld) {
this.ld = ld;
}
public void setTd(TradeDao td) {
this.td = td;
}
}
如果丟擲異常後臺就會輸出異常資訊。最後
spring的配置檔案才是最重要的,所以來看下applicationContext.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="
http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 註冊資料來源 (spring內建資料庫源)-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 註冊資料庫屬性檔案 方式一 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean>
<!-- 註冊事務管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 生成service的事務代理物件 -->
<bean id="serviceProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 目標物件 -->
<property name="target" ref="textS" />
<!-- 跟事務管理器關聯 -->
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="to*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-MyException</prop>
</props>
</property>
</bean>
<!-- 註冊Dao物件 -->
<!-- 開戶Dao -->
<bean id="zhuceD" class="com.it.DaoImp.ZhuCeDaoImp">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 登入Dao -->
<bean id="loginD" class="com.it.DaoImp.LoginDaoImp">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 股票操作Dao -->
<bean id="tradeD" class="com.it.DaoImp.TradeDaoImp">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 註冊Service物件 -->
<bean id="textS" class="com.it.ServiceImp.TestServiceImp">
<property name="zd" ref="zhuceD"></property>
<property name="ld" ref="loginD"></property>
<property name="td" ref="tradeD"></property>
</bean>
</beans>
相關推薦
Spring練習:JDBC模板和事務回滾
SSH框架是每個學生畢業前都必須掌握的一門技術,所以這裡就用Spring的JDBC模板和自定義異常讓事務回滾來做一個練習。主要用到的是spring和struts2框架來操作,這裡暫時沒用Hibernate來對資料進行操作。 一、練習要求。 要求寫一個使用者購買股票的專案,使
四、spring的JDBC模板和事務管理
Spring的JDBC模板 Spring是JavaEE開發的一站式框架,對各種持久化技術都提供了簡單的模板 ORM持久化技術 模板類 JDBC org.springframework.jdbc.core.JdbcTemplate
事務和事務回滾
mysq back 事務 sql 結束 cti 數據庫 ons transacti 1、定義:一件事從開始發生到結束的整個過程 2、作用:確保數據的一致性 3、事務和事務回滾的應用 1、SQL命令會 autocommit 到數據庫執行 2、事務操作
Spring入門(三)— AOP註解、jdbc模板、事務
list() 規範 行數 get attribute 樂觀鎖 過濾 callback 賬號 一、AOP註解開發 導入jar包 aop聯盟包、 aspectJ實現包 、 spring-aop-xxx.jar 、 spring-aspect-xxx.jar 導入約束 a
Day3-Spring的事務管理、Spring框架的JDBC模板
今天內容 1. Spring框架的AOP之註解的方式2. Spring框架的JDBC模板3. Spring框架的事務管理 案例一:使用Spring框架的AOP技術對DAO層的功能進行增強 案例一:使用Spring框架的AOP技術對DAO層的功能進行增強 1. 使用Spring框架的
spring事務管理,基於xml配置完成事務回滾;spring中資料庫表中欄位名和pojo中屬性名不一致時候,實現RowMapper介面手動封裝
宣告使用JDK8,spring5.0.7, 測試說明: service 層 宣告介面進行轉賬,從A轉賬B ,然後對AB 進行更新操作,在事務中對find方法開啟 只讀許可權,無法進行更新操作,造成事務回滾進行測試事務; 主要測試方法:* void tra
Spring--04(Spring的JDBC操作和事務操作)
1.Spring 的 JDBC 的模板 Spring 提供了很多持久層技術的模板類簡化程式設計:  
Java學習筆記(12)Spring JDBC框架和事務管理
Spring JDBC框架 JDBC框架概述: 在使用普通的 JDBC 資料庫時,就會很麻煩的寫不必要的程式碼來處理異常,開啟和關閉資料庫連線等。但 Spring JDBC 框架負責所有的低層細節,從開始開啟連線,準備和執行 SQL 語句,處理異常,處理
事務: spring+hibernate實現事務回滾及其他
程式碼控制的事務管理2. 引數化配置的事務管理下面就這兩種方式進行介紹。u 程式碼控制的事務管理首先,進行以下配置,假設配置檔案為(Application-Context.xml):<beans><bean id="dataSource" class="org.apache.commons.
java之Spring事務回滾和Ehcache配置
弄了一大早,終於配好了事務,事務的掃描包配好,Ehcache就是切面的問題,一切問題也迎刃而解。。。 一、Spring事務回滾 1、applicationContext.xml中配置 <!--spring 掃包 @Service .....
Spring事務回滾和異常類
1、異常的一些基本知識 異常的架構 異常的繼承結構:Throwable為基類,Error和Exception繼承Throwable。Error和RuntimeException及其子類成為未檢查異常(unchecked),其它異常成為已檢查異常(checked)。
Spring 實現部分事務回滾
light back true prop 回滾 sage .class lba aaa 例如有業務需求,在catch異常後,catch塊內把異常的信息存入到數據庫,而catch外的數據全部回滾 try { ....... aaaService.save();
回滾的意義---JDBC事務回滾探究
final cti span net etc rom tle img round JDBC手動事務提交回滾的常見寫法一直是rollback寫在commit的catch之後: try{ conn.setAutoCommit(false); ps.execu
spring框架總結(04)----介紹的是Spring中的JDBC模板
aos 不用 get interface comm use clas table oid 1.1 Jdbc模板概述 它是spring框架中提供的一個對象,是對原始Jdbc API對象的簡單封裝。spring框架為我們提供了很多的操作模板類,入下圖所示: 我們今天的
淺談Spring中的事務回滾
spec style try 常見 產生原因 turn prop ret run 使用Spring管理事務過程中,碰到過一些坑,因此也稍微總結一下,方便後續查閱。1.代碼中事務控制的3種方式編程式事務:就是直接在代碼裏手動開啟事務,手動提交,手動回滾。優點就是可以靈
哪些異常是RuntimeException?Sql異常屬於RuntimeException嗎?Spring下SQL異常事務回滾
tail 好的 duplicate 代碼 blog 後拋 ase owa 接口文檔 一,為什麽框架中根本沒有對Exception的一般子類進行回滾配置,異常發生時,事務都進行了回滾 ,說好的只會對RuntimeException(Unchecked 非受檢異常)回滾呢?
Python實踐練習:電話號碼和 E-mail 地址提取程序
system 剪切板 http con cisco jobs 什麽 python3 sts 題目: 假設你有一個無聊的任務,要在一篇長的網頁或文章中,找出所有電話號碼和郵件地址。如果手動翻頁,可能需要查找很長時間。如果有一個程序,可以在剪貼板的文本中查找電話號碼和 E-ma
spring事務回滾的多種方式
轉:https://www.cnblogs.com/zeng1994/p/8257763.html start 看下下面的說明,會對理解本人貼出的程式碼有幫助。 1.程式碼中事務控制的3種方式 程式設計式事務:就是直接在程式碼裡手動開啟事務,手動提交,手動回滾。優點就是可以靈活控制,缺點
Spring Cloud:配置中心和訊息匯流排(終結版)(09)
我們在springcloud(七):配置中心svn示例和refresh中講到,如果需要客戶端獲取到最新的配置資訊需要執行refresh,我們可以利用webhook的機制每次提交程式碼傳送請求來重新整理客戶端,當客戶端越來越多的時候,需要每個客戶端都執行一遍,這種方案就不太適合了。使用Spring C
spring手動控制事務回滾
在catch語塊中增加TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); import org.springframework.transaction.interceptor.TransactionAs