java下一頁,Spring 框架 DAO 與 事務 的總結

 2023-09-30 阅读 20 评论 0

摘要:一:帝國之倉-DAO 1.持久層支持 為什么需要使用Spring對持久層的支持?1):原生操作持久層API方式,麻煩.2):Spring對事務支持非常優秀.傳統JDBC:1:代碼臃腫,重復2:處理異常3:控制事務Spring JDBC:1:簡潔,優雅,簡單2:運行異常3:Spring事務管理![Spring為什么對持久層提供技術支持]

一:帝國之倉-DAO

1.持久層支持

為什么需要使用Spring對持久層的支持?1):原生操作持久層API方式,麻煩.2):Spring對事務支持非常優秀.傳統JDBC:1:代碼臃腫,重復2:處理異常3:控制事務Spring JDBC:1:簡潔,優雅,簡單2:運行異常3:Spring事務管理![Spring為什么對持久層提供技術支持](https://img-blog.csdn.net/20180406231810368?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)![Spring提供的對應模板類](https://img-blog.csdn.net/2018040623194871?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

2.JDBC

需求:使用JDBC完成CRUD操作.依賴jar:mysql-connector-java-5.x.11.jar:MySQL驅動包druid連接池spring-jdbc-版本.RELEASE.jar:支持JDBCspring-tx-版本.RELEASE.jar:支持事務

dao

public interface EmployeeDAO {void save(Employee emp);void update(Employee emp);void delete(Long id);Employee get(Long id);List<Employee> listAll();
}

impl

public class EmployeeDAOImpl implements EmployeeDAO{private JdbcTemplate jdbcTemplate;public void setDataSource(DataSource dataSource){this.jdbcTemplate = new JdbcTemplate(dataSource);}public void save(Employee emp) {jdbcTemplate.update("INSERT INTO employee (name,age) VALUES (?,?)",emp.getName(),emp.getAge());}public void update(Employee emp) {jdbcTemplate.update("UPDATE employee SET name=? ,age=? WHERE id=?",emp.getName(),emp.getAge(),emp.getId());}public void delete(Long id) {jdbcTemplate.update("DELETE FROM employee where id = ?",id);}public Employee get(Long id) {List<Employee> list = jdbcTemplate.query("SELECT id,name,age eage from employee where id = ?",new Object[]{id},(rs,rowNum)->{//lanmda表達式其實就是匿名內部類的縮寫,面向行數的編程Employee e = new Employee();e.setId(rs.getLong("id"));e.setName(rs.getString("name"));e.setAge(rs.getInt("eage"));return e;   });return list.size()==1? list.get(0):null;}public List<Employee> listAll() {return jdbcTemplate.query("SELECT id,name,age eage from employee",new Object[]{},new RowMapper<Employee>(){//把每一行結果集映射成一個Employee對象public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {Employee e = new Employee();e.setId(rs.getLong("id"));e.setName(rs.getString("name"));e.setAge(rs.getInt("eage"));return e;}});}
}

java下一頁,App-context.xml

<context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><property name="initialSize" value="${jdbc.initialSize}"></property></bean><!-- 配置DAO --><bean id="employeeDAO" class="cn.wolfcode.dao.imp.EmployeeDAOImpl"><property name="dataSource" ref="dataSource" ></property></bean>
    1:不建議使用QueryForObject因為得到的結果如果沒有會報錯2:回顧了一下lambda表達式.3:解釋了JDBC底層是怎么處理結果集的![解釋JDBC底層處理結果集](https://img-blog.csdn.net/20180407004514737?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

Spring JDBC的其他設計

    1:給jdbcTemplate的一個基類(父類)  將需要的類繼承與JdbcDaoSupport,但是任然要為其父類注入DataSource屬性然后super.getJdbcTemplate().調用的方法![hibernate等其他類的基類圖](https://img-blog.csdn.net/20180407012449666?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)2:將參數用NamedParameterJdbcTemplate來設置NamedParameterJdbcTemplate namedParameterJdbcTemplate = null;namedParameterJdbcTemplate.update("INSERT INTO employee (name,age) VALUES (:ename,:eage)",new HashMap(){{this.put("ename",emp.getName());this.put("eage", emp.getAge());}});![具體參數設置細節](https://img-blog.csdn.net/20180407012153524?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

二:帝國之盾-TX

1.引出事務

dao

    ![根據銀行轉賬案例引出事務](https://img-blog.csdn.net/20180407122553180?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)public class AccountDAOImpl implements IAccountDAO{private JdbcTemplate jdbcTemplate;public void setDataSource(DataSource dataSource){this.jdbcTemplate = new JdbcTemplate(dataSource);}public void transOut(Long outId, int money) {jdbcTemplate.update("UPDATE account set balance = balance - ? where id = ?",money,outId);}public void transIn(Long inId, int money) {jdbcTemplate.update("UPDATE account set balance = balance + ? where id = ?",money,inId);}
}

service

public class AccountServiceImpl implements IAccountService{private IAccountDAO dao;public void setDao(IAccountDAO dao) {this.dao = dao;}public void trans(Long outId, Long inId, int money) {dao.transOut(outId, money);int i = 3 / 0;dao.transIn(inId, money);}
}

為什么不建議學django。App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {@Autowiredprivate IAccountService service;@Testpublic void testTrans() throws Exception {service.trans(10086L,10010L,1000);}
}

2.事務回顧

    ![何為數據庫事務](https://img-blog.csdn.net/20180407122703713?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)數據庫并發問題:并發問題類型          產生原因和效果第一類丟失更新        兩個事務更新相同數據,如果一個事務提交,另一個事務回滾,第一個事務的更新會被回滾臟讀                 第二個事務查詢到第一個事務未提交的跟新數據,第二個事務根據該數據執行,但第一個事務回滾第二個事務操作臟數據虛讀                一個事務查詢到另一個事務已經提交的新數據,導致導致多次查詢數據不一致不可重復讀           一個事務查詢到另一個事務已經修改的數據,導致多次查詢數據不一致第二類丟失數據        多個事務同時讀取相同數據,并完成各自的事務提交,導致最后一個事務提交會覆蓋前面所有事務對數據的改變
    ![事務的隔離級別](https://img-blog.csdn.net/20180407141043712?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)默認情況下MySQL不會出現幻讀.除非:select * from 表名 lock in share mode;MySQL中鎖基于索引機制,也不會出現第一類丟失更新.Oracle支持 READ COMMITED(缺省) 和 SERIALIZABLE.MySQL支持 四種隔離級別, 缺省為REPEATABLE READ.隔離級別如何選用:隔離界別越高,數據庫事務并發執行性能越差,能處理的操作越少.因此在實際項目開發中為了考慮并發性能一般使用READ COMMITED.它能避免丟失跟新和臟讀盡管不可重復讀和幻讀不能避免,更多的情況下使用悲觀鎖或樂觀鎖來解決.
事務的類型:本地事務:就是普通事務,能保證單臺數據庫上的操作ACID,被限定在一臺數據庫上.分布式事務:涉及多個數據庫源的事務,即跨越多臺同類或異類數據庫的事務(由每臺數據庫的本地事務組成的),分布式事務旨在保證這些本地事務的所有操作ACID,使事務可以跨越多臺數據庫;JDBC事務和JTA事務:JDBC事務:就是數據庫事務類型中的本地事務,通過Conenction對象的控制來管理事務;JTA事務:JTA指(Java Transaction API).是Java EE數據庫事務規范,JTA只提供了事務管理接口,由應用程序服務器廠商提供實現,JTA事務比JDBC更強大,支持分布式事務.按是否通過編程實現事務有聲明式事務和編程式事務:編程式事務:通過編寫代碼來管理事務.聲明式事務:通過注解或XML配置來管理事務.

3.Spring對事務支持的API

PlatformTransactionManager:根據TransactionDefinition提供的事務屬性配置信息,創建事務.平臺的事務管理器,是多種事務管理器的基類,覆蓋了處理事務的方法.public interface PlatformTransactionManager {//根據事務定義的環境中返回一個已經存在的事務,如果不存在,則新建一個.TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;//提交事務void commit(TransactionStatus status) throws TransactionException;//回滾事務void rollback(TransactionStatus status) throws TransactionException;}TransactionDefinition:封裝事務的隔離級別和超時時間,是否為只讀事務和傳播規則等事務屬性.TransactionStatus:封裝了事務的具體運行狀態,如是否新開啟事務,是否已經提交事務,設置當前事務為rollback-only等.它們三者之間有關聯的.
    Hibernate  :  HibernateTransactionManagerJDBC/MyBatis: DataSourceTransactionManager![如何正確的使用JDBC/MyBatis等連接池](https://img-blog.csdn.net/20180407145436503?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

4.事務的傳播規則

    ![事務的傳播行為](https://img-blog.csdn.net/20180407151009598?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)寄生事務并不是所有的事務管理器都支持,比如HibernateTransactionManager默認就不支持,需要手動去開啟JDBCMyBatis的事務管理器:DataSourceTransactionManager:默認就是支持的.

5.事務配置

    ![<tx:method name=""/>里面的屬性配置](https://img-blog.csdn.net/20180407160349699?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

通過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"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd" ><context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><property name="initialSize" value="${jdbc.initialSize}"></property></bean><!-- 配置DAO --><bean id="accountDAOImpl" class="cn.wolfcode.dao.imp.AccountDAOImpl"><property name="dataSource" ref="dataSource" ></property></bean><!-- 配置Service --><bean id="accountServiceImpl" class="cn.wolfcode.service.impl.AccountServiceImpl"><property name="dao" ref="accountDAOImpl"></property></bean><!-- ============================================================================= --><!-- 1:WHAT:配置JDBC事務管理器 --><!-- 記得拷貝TX事務這個包 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 2:WHEN:配置事務管理器增強 --><tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><tx:method name="trans"/></tx:attributes> </tx:advice><!-- 3:WHERE:配置一個切面 --><aop:config><aop:pointcut expression="execution(* cn.wolfcode.service.*Service.*(..))" id="txPointCut"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config><!-- ============================================================================= --><!-- 配置一個CRUD的通用事務的配置 --><tx:advice id="crudAdvice" transaction-manager="txManager"><tx:attributes><!-- service中的查詢方法 --><tx:method name="get*" read-only="true" propagation="REQUIRED"/><tx:method name="list" read-only="true" propagation="REQUIRED"/><tx:method name="query*" read-only="true" propagation="REQUIRED"/><!-- service中其他方法(非查詢) --><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice></beans>

vue和django一點都不搭。6.使用注解配置

domain

@Data
public class Account {private Long id;private int balance;
}

dao

public interface IAccountDAO {/*** 從指定賬戶轉出多少錢* @param outId* @param money*/void transOut(Long outId,int money);/*** 從指定賬戶轉入多少錢* @param inId* @param money*/void transIn(Long inId,int money);
}

impl

@Repository
public class AccountDAOImpl implements IAccountDAO{private JdbcTemplate jdbcTemplate;@Autowiredpublic void setDataSource(DataSource dataSource){this.jdbcTemplate = new JdbcTemplate(dataSource);}public void transOut(Long outId, int money) {jdbcTemplate.update("UPDATE account set balance = balance - ? where id = ?",money,outId);}public void transIn(Long inId, int money) {jdbcTemplate.update("UPDATE account set balance = balance + ? where id = ?",money,inId);}
}

service

public interface IAccountService {/*** 從指定賬戶轉出指定金額給另一個賬戶* @param outId* @param inId* @param money*/void trans(Long outId,Long inId,int money);
}

impl

@Service
@Transactional
public class AccountServiceImpl implements IAccountService{@Autowiredprivate IAccountDAO dao;public void trans(Long outId, Long inId, int money) {dao.transOut(outId, money);int i = 3 / 0;dao.transIn(inId, money);}@Transactional(readOnly=true)public void list(){}
}

新手學flask還是django,App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {@Autowiredprivate IAccountService service;@Testpublic void testTrans() throws Exception {service.trans(10086L,10010L,1000);}
}

App-Context.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"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd" ><!-- DI注解解析器 --><context:annotation-config/><!-- IoC注解解釋器 --><context:component-scan base-package="cn.wolfcode"/><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- TX注解解釋器 --><tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/><!-- 從classpath的根路徑去加載db.properties文件 -->               <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property><property name="initialSize" value="${jdbc.initialSize}"></property></bean></beans>
    1:切記在xml文件中配置   DataSourceTransactionManager  <bean>屬性因為它是JDBC/MyBatis專屬事務<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>2:記得配置 TX 注解解析器<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>3:@Transactional()給需要使用事務的類配置,配置到類上表示類下面的所有方法都使用事務,()可以設置事務的屬性@Transactional()配置到某個方法上,設置的屬性,就覆蓋所有類的事務屬性,就可以單獨設置,比如給查詢方法設置只讀@Transactional(readOnly=true)public void list(){}

6.使用Java-Config來做配置

service

//其余跟上面代碼一樣
@Service                    
@Transactional              
public class AccountServiceImpl implements IAccountService{@Autowiredprivate IAccountDAO dao;public void trans(Long outId, Long inId, int money) {dao.transOut(outId, money);//int i = 3 / 0;dao.transIn(inId, money);}
}

AppConfig

//當前項目的配置類,好比是applicationContext.xml
@Configuration              //標志當前類為一個配置類
@Import(DataSourceConfig.class)//包含其他配置類
@ComponentScan              //IoC注解解析器   DI注解默認引入進來 不寫的話從當前的包,包括子包都要掃描 
@EnableTransactionManagement//事務注解解析器
public class AppConfig {//創建事務管理的Bean@Beanpublic DataSourceTransactionManager txManager(DataSource ds){return new DataSourceTransactionManager(ds);}
}

DataSourceConfig

//當前項目的連接池的配置類
@Configuration
@PropertySource("classpath:db.properties")
public class DataSourceConfig {@Value("${jdbc.driverClassName}")private String driverClassName;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;@Value("${jdbc.initialSize}")private int initialSize;//創建連接池的Bean@Beanpublic DataSource dataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driverClassName);ds.setUrl(url);ds.setUsername(username);ds.setPassword(password);ds.setInitialSize(initialSize);return ds;}
}

python web為什么不火,App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=AppConfig.class)
public class App {@Autowiredprivate IAccountService service;@Testpublic void testTrans() throws Exception {service.trans(10086L,10010L,1000);}
}

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/105277.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息