<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    空間站

    北極心空

      BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
      15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

    在沒(méi)有使用 Spring 提供的 Open Session In View 情況下,因需要在 service(or Dao) 層里把 session 關(guān)閉,所以 lazy loading true 的話,要在應(yīng)用層內(nèi)把關(guān)系集合都初始化,如 company.getEmployees() ,否則 Hibernate session already closed Exception; ??? Open Session In View 提供了一種簡(jiǎn)便的方法,較好地解決了 lazy loading 問(wèn)題 .

    ??? 它有兩種配置方式OpenSessionInViewInterceptor OpenSessionInViewFilter(具體參看SpringSide) ,功能相同,只是一個(gè)在 web.xml 配置,另一個(gè)在 application.xml 配置而已。

    ??? Open Session In View request session 綁定到當(dāng)前 thread 期間一直保持 hibernate session open 狀態(tài),使 session request 的整個(gè)期間都可以使用,如在 View 層里 PO 也可以 lazy loading 數(shù)據(jù),如 ${ company.employees } 。當(dāng) View 層邏輯完成后,才會(huì)通過(guò) Filter doFilter 方法或 Interceptor postHandle 方法自動(dòng)關(guān)閉 session


    						
    OpenSessionInViewInterceptor配置
    1. <beans>
    2. <bean name="openSessionInViewInterceptor"
    3. class ="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
    4. <property name="sessionFactory">
    5. <ref bean="sessionFactory"/>
    6. </property>
    7. </bean>
    8. <bean id="urlMapping"
    9. class ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    10. <property name="interceptors">
    11. <list>
    12. <ref bean="openSessionInViewInterceptor"/>
    13. </list>
    14. </property>
    15. <property name="mappings">
    16. ...
    17. </property>
    18. </bean>
    19. ...
    20. </beans>
    						
    OpenSessionInViewFilter配置
    1. <web-app>
    2. ...
    3. <filter>
    4. <filter-name>hibernateFilter</filter-name>
    5. <filter-class>
    6. org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    7. </filter-class>
    8. <!-- singleSession默認(rèn)為true,若設(shè)為false則等于沒(méi)用OpenSessionInView -->
    9. <init-param>
    10. <param-name>singleSession</param-name>
    11. <param-value>true</param-value>
    12. </init-param>
    13. </filter>
    14. ...
    15. <filter-mapping>
    16. <filter-name>hibernateFilter</filter-name>
    17. <url-pattern>*.do</url-pattern>
    18. </filter-mapping>
    19. ...
    20. </web-app>

    很多人在使用OpenSessionInView過(guò)程中提及一個(gè)錯(cuò)誤:

    						
    1. org.springframework.dao.InvalidDataAccessApiUsageException: Write operations
    2. are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into
    3. FlushMode.AUTO or remove 'readOnly' marker from transaction definition

    看看OpenSessionInViewFilter里的幾個(gè)方法

    						
    1. protected void doFilterInternal ( HttpServletRequest request,
      HttpServletResponse response,FilterChain filterChain)
      throws ServletException, IOException
      {
       SessionFactory sessionFactory = lookupSessionFactory();
       logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
       Session session = getSession(sessionFactory);
       TransactionSynchronizationManager.bindResource
      (
        sessionFactory, new SessionHolder(session));
       try
      {
        filterChain.doFilter(request, response);
       
      }
       finally
      {
       TransactionSynchronizationManager.unbindResource(sessionFactory);
       logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
       closeSession(session, sessionFactory);
       
      }
      }





      ?
    2. protected Session getSession(SessionFactory sessionFactory )
      throws DataAccessResourceFailureException
      {
       Session session = SessionFactoryUtils.getSession(sessionFactory, true);
       session.setFlushMode(FlushMode.NEVER);
       return session;
      }

    3. protected
      void closeSession ( Session session, SessionFactory sessionFactory )
      throws CleanupFailureDataAccessException
      {
       SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory);
      }

    ??????????關(guān)于綁定session的方式,通過(guò)看spring里TransactionSynchronizationManager的實(shí)現(xiàn),發(fā)現(xiàn):它維護(hù)一個(gè)java.lang.ThreadLocal類(lèi)型的resources,resources負(fù)責(zé)持有線程局部變量,這里resources持有的是一個(gè)HashMap,通過(guò)TransactionSynchronizationManager.bindResource()方法在map里綁定和線程相關(guān)的所有變量到他們的標(biāo)識(shí)上,包括如上所述的綁定在sessionFactory上的線程局部session。sessionHolder只不過(guò)是存放可以hold一個(gè)session并可以和transtaction同步的容器。可以看到OpenSessionInViewFilter在getSession的時(shí)候,會(huì)把獲取回來(lái)的session的flush mode 設(shè)為FlushMode.NEVER。然后把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個(gè)過(guò)程都使用同一個(gè)session,在請(qǐng)求過(guò)后再接除該sessionFactory的綁定,最后closeSessionIfNecessary根據(jù)該session是否已和transaction綁定來(lái)決定是否關(guān)閉session。綁定以后,就可以防止每次不會(huì)新開(kāi)一個(gè)Session呢?看看HibernateDaoSupport的情況:

    						
    								     1.  public
    								final void setSessionFactory(SessionFactory sessionFactory) {    2.      this.hibernateTemplate = new HibernateTemplate(sessionFactory);    3.  }    4.  protectedfinal HibernateTemplate getHibernateTemplate() {    5.      return hibernateTemplate;    6.  }
    				

    ??????? 我們的DAO將使用這個(gè)template進(jìn)行操作.

    public abstract class BaseHibernateObjectDao extends HibernateDaoSupport
    implements BaseObjectDao {
    ???? protected BaseEntityObject getByClassId(final long id) {
    ??????????? ????BaseEntityObject obj =(BaseEntityObject) getHibernateTemplate().execute(new HibernateCallback() {
    ??????????????? ??????? public Object doInHibernate(Session session) throws HibernateException {
    ????????????????? ????????????????? return session.get(getPersistentClass(),new Long(id));
    ???????????? ?????????? }
    ???????????? ?? });
    ????????????? ??return obj;
    ??? ??}
    ???? public void save(BaseEntityObject entity) {
    ???????????????? ?getHibernateTemplate().saveOrUpdate(entity);
    ???? }

    ??? public void remove(BaseEntityObject entity) {
    ???????????? ?try {
    ???????????????????? getHibernateTemplate().delete(entity);
    ????????????? } catch (Exception e) {
    ????????????????????? throw new FlexEnterpriseDataAccessException(e);
    ???????????? }
    ???? }

    ????? public void refresh(final BaseEntityObject entity) {
    ???????????????getHibernateTemplate().execute(new HibernateCallback() {
    ????????????????????????? public Object doInHibernate(Session session) throws HibernateException {
    ????????????????????????????????????? session.refresh(entity);
    ????????????????????????????????????? return null;
    ??????????????????????? ??}
    ????????????? ?});
    ????? }

    ???? public void replicate(final Object entity) {
    ??????????????? getHibernateTemplate().execute(new HibernateCallback() {
    ????????????????????????? public Object doInHibernate(Session session)throws HibernateException {
    ????????????????????????????????????? session.replicate(entity,ReplicationMode.OVERWRITE);
    ????????????????????????????????????? return null;
    ?????????????? }
    ?????????????? ?});
    ????? }
    }

    ??????? 而HibernateTemplate試圖每次在execute之前去獲得Session,執(zhí)行完就力爭(zhēng)關(guān)閉Session

    						
    								  1. public
    								Object execute(HibernateCallback action) throws DataAccessException {??2. ???Session session = (!this.allowCreate ???3. ?????????SessionFactoryUtils.getSession(getSessionFactory(),   4.                false) :??5. ?????????SessionFactoryUtils.getSession(getSessionFactory(),  6.                 getEntityInterceptor(),  7.                 getJdbcExceptionTranslator()));??8. ????boolean existingTransaction =    9.         TransactionSynchronizationManager.hasResource(getSessionFactory());??10.????if (!existingTransaction && getFlushMode() == FLUSH_NEVER) {??11.??????????session.setFlushMode(FlushMode.NEVER);??12.????}??13.????try {??14.??????????Object result = action.doInHibernate(session);??15.??????????flushIfNecessary(session, existingTransaction);??16.??????????return result;??17.????}??18.????catch (HibernateException ex) {??19.??????????throw convertHibernateAccessException(ex);??20.????}??21.????finally {??22.??????????SessionFactoryUtils.closeSessionIfNecessary(  23.                  session, getSessionFactory());??24.????}  25. }
    				

    ????? 而這個(gè)SessionFactoryUtils能否得到當(dāng)前的session以及closeSessionIfNecessary是否真正關(guān)閉session,端取決于這個(gè)session是否用sessionHolder和這個(gè)sessionFactory在我們最開(kāi)始提到的TransactionSynchronizationManager綁定。

    ???? publicstaticvoidcloseSessionIfNecessary(Session session, SessionFactory sessionFactory)

    						
    1. throws CleanupFailureDataAccessException {
    2. if ( session == null ||
      TransactionSynchronizationManager.hasResource(sessionFactory)){
    3. return ;
    4. }
    5. logger.debug("Closing Hibernate session");
    6. try {
    7. session.close();
    8. }
    9. catch ( JDBCException ex){
    10. // SQLException underneath
    11. throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex.getSQLException());
    12. }
    13. catch ( HibernateException ex){
    14. throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex);
    15. }
    16. }

    ??? 在這個(gè)過(guò)程中,若HibernateTemplate 發(fā)現(xiàn)自當(dāng)前session有不是readOnly的transaction,就會(huì)獲取到FlushMode.AUTO Session,使方法擁有寫(xiě)權(quán)限。也即是,如果有不是readOnly的transaction就可以由Flush.NEVER轉(zhuǎn)為Flush.AUTO,擁有insert,update,delete操作權(quán)限,如果沒(méi)有transaction,并且沒(méi)有另外人為地設(shè)flush model的話,則doFilter的整個(gè)過(guò)程都是Flush.NEVER。所以受transaction保護(hù)的方法有寫(xiě)權(quán)限,沒(méi)受保護(hù)的則沒(méi)有。

    1. 可能的解決方式有:
      1、將singleSession設(shè)為false,這樣只要改web.xml,缺點(diǎn)是Hibernate Session的Instance可能會(huì)大增,使用的JDBC Connection量也會(huì)大增,如果Connection Pool的maxPoolSize設(shè)得太小,很容易就出問(wèn)題。
      2、在控制器中自行管理Session的FlushMode,麻煩的是每個(gè)有Modify的Method都要多幾行程式。
      ????? session.setFlushMode(FlushMode.AUTO);
      ????? session.update(user);
      ????? session.flush();
      3、Extend OpenSessionInViewFilter,Override protected Session getSession(SessionFactory sessionFactory),將FlushMode直接改為Auto。
      4、讓方法受Spring的事務(wù)控制。這就是常使用的方法:

    采用spring的事務(wù)聲明,使方法受transaction控制

    				
    1. ? <bean id="baseTransaction"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
      ? ? ? ? ? abstract="true">
      ? ? ? ? <property name="transactionManager" ref="transactionManager"/>
      ? ? ? ? <property name="proxyTargetClass" value="true"/>
      ? ? ? ? <property name="transactionAttributes">
      ? ? ? ? ? ? <props>
      ? ? ? ? ? ? ? ? <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
      ? ? ? ? ? ? ? ? <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
      ? ? ? ? ? ? ? ? <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
      ? ? ? ? ? ? ? ? <prop key="save*">PROPAGATION_REQUIRED</prop>
      ? ? ? ? ? ? ? ? <prop key="add*">PROPAGATION_REQUIRED</prop>
      ? ? ? ? ? ? ? ? <prop key="update*">PROPAGATION_REQUIRED</prop>
      ? ? ? ? ? ? ? ? <prop key="remove*">PROPAGATION_REQUIRED</prop>
      ? ? ? ? ? ? </props>
      ? ? ? ? </property>
      ? ? </bean>

    2. ? ? <bean id="userService" parent="baseTransaction">
      ? ? ? ? <property name="target">
      ? ? ? ? ? ? <bean class="com.phopesoft.security.service.impl.UserServiceImpl"/>
      ? ? ? ? </property>
      ? ? </bean>

    對(duì)于上例,則以save,add,update,remove開(kāi)頭的方法擁有可寫(xiě)的事務(wù),如果當(dāng)前有某個(gè)方法,如命名為importExcel(),則因沒(méi)有transaction而沒(méi)有寫(xiě)權(quán)限,這時(shí)若方法內(nèi)有insert,update,delete操作的話,則需要手動(dòng)設(shè)置flush model為Flush.AUTO,如

    				
    1. session.setFlushMode(FlushMode.AUTO);
    2. session.save(user);
    3. session.flush();

    ?????盡管Open Session In View看起來(lái)還不錯(cuò),其實(shí)副作用不少。看回上面OpenSessionInViewFilter的doFilterInternal方法代碼,這個(gè)方法實(shí)際上是被父類(lèi)的doFilter調(diào)用的,因此,我們可以大約了解的OpenSessionInViewFilter調(diào)用流程: request(請(qǐng)求)->open session并開(kāi)始transaction->controller->View(Jsp)->結(jié)束transaction并close session.

    ???? 一切看起來(lái)很正確,尤其是在本地開(kāi)發(fā)測(cè)試的時(shí)候沒(méi)出現(xiàn)問(wèn)題,但試想下如果流程中的某一步被阻塞的話,那在這期間connection就一直被占用而不釋放。最有可能被阻塞的就是在寫(xiě)Jsp這步,一方面可能是頁(yè)面內(nèi)容大,response.write的時(shí)間長(zhǎng),另一方面可能是網(wǎng)速慢,服務(wù)器與用戶(hù)間傳輸時(shí)間久。當(dāng)大量這樣的情況出現(xiàn)時(shí),就有連接池連接不足,造成頁(yè)面假死現(xiàn)象。

    Open Session In View是個(gè)雙刃劍,放在公網(wǎng)上內(nèi)容多流量大的網(wǎng)站請(qǐng)慎用。

    ?

    另外:這樣會(huì)產(chǎn)生一點(diǎn)危險(xiǎn)性,畢竟把數(shù)據(jù)庫(kù)訪問(wèn)的環(huán)境放到了表現(xiàn)層。(:用VO)

    ?


    ?

    ?


    ?

    ?

    ??????? Hibernate是對(duì)JDBC的輕量級(jí)對(duì)象封裝,Hibernate本身是不具備Transaction處理功能的,Hibernate的Transaction實(shí)際上是底層的JDBC Transaction的封裝,或者是JTA Transaction的封裝,下面我們?cè)敿?xì)的分析:

      Hibernate可以配置為JDBCTransaction或者是JTATransaction,這取決于你在hibernate.properties中的配置:

    #hibernate.transaction.factory_class
    net.sf.hibernate.transaction.JTATransactionFactory
    #hibernate.transaction.factory_class
    net.sf.hibernate.transaction.JDBCTransactionFactory

      如果你什么都不配置,默認(rèn)情況下使用JDBCTransaction,如果你配置為:

    hibernate.transaction.factory_class
    net.sf.hibernate.transaction.JTATransactionFactory

      將使用JTATransaction,不管你準(zhǔn)備讓Hibernate使用JDBCTransaction,還是JTATransaction,我的忠告就是什么都不配,將讓它保持默認(rèn)狀態(tài),如下:

    #hibernate.transaction.factory_class
    net.sf.hibernate.transaction.JTATransactionFactory
    #hibernate.transaction.factory_class
    net.sf.hibernate.transaction.JDBCTransactionFactory

      在下面的分析中我會(huì)給出原因。

      一、JDBC Transaction

      看看使用JDBC Transaction的時(shí)候我們的代碼例子:

    Session session = sf.openSession();
    Transaction tx = session.beginTransactioin();
    ...
    session.flush();
    tx.commit();
    session.close();
      這是默認(rèn)的情況,當(dāng)你在代碼中使用Hibernate的Transaction的時(shí)候?qū)嶋H上就是JDBCTransaction。那么JDBCTransaction究竟是什么東西呢?來(lái)看看源代碼就清楚了:

      Hibernate2.0.3源代碼中的類(lèi)

      net.sf.hibernate.transaction.JDBCTransaction:

    public void begin() throws HibernateException {
    ...
    if (toggleAutoCommit) session.connection().setAutoCommit(false);
    ...
    }
      這是啟動(dòng)Transaction的方法,看到 connection().setAutoCommit(false) 了嗎?是不是很熟悉?

      再來(lái)看

    public void commit() throws HibernateException {
    ...
    try {
    if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();
    try {
    session.connection().commit();
    committed = true;
    }
    ...
    toggleAutoCommit();
    }

      這是提交方法,看到connection().commit() 了嗎?下面就不用我多說(shuō)了,這個(gè)類(lèi)代碼非常簡(jiǎn)單易懂,通過(guò)閱讀使我們明白Hibernate的Transaction都在干了些什么?我現(xiàn)在把用Hibernate寫(xiě)的例子翻譯成JDBC,大家就一目了然了:

    Connection conn = ...;????????????? ?<--- session = sf.openSession();
    conn.setAutoCommit(false);?? <--- tx = session.beginTransactioin();
    ... <--- ...
    conn.commit();?????????????????????????? <--- tx.commit(); (對(duì)應(yīng)左邊的兩句)
    conn.setAutoCommit(true);
    conn.close();????????????????????????????? <--- session.close();

      看明白了吧,Hibernate的JDBCTransaction根本就是conn.commit而已,根本毫無(wú)神秘可言,只不過(guò)在Hibernate中,Session打開(kāi)的時(shí)候,就會(huì)自動(dòng)conn.setAutoCommit(false),不像一般的JDBC,默認(rèn)都是true,所以你最后不寫(xiě)commit也沒(méi)有關(guān)系,由于Hibernate已經(jīng)把AutoCommit給關(guān)掉了,所以用Hibernate的時(shí)候,你在程序中不寫(xiě)Transaction的話,數(shù)據(jù)庫(kù)根本就沒(méi)有反應(yīng)。?

    ?二、JTATransaction

    如果你在EJB中使用Hibernate,或者準(zhǔn)備用JTA來(lái)管理跨Session的長(zhǎng)事務(wù),那么就需要使用JTATransaction,先看一個(gè)例子:

    javax.transaction.UserTransaction tx = new InitialContext().lookup("javax.transaction.UserTransaction");

    Session s1 = sf.openSession();
    ...
    s1.flush();
    s1.close();
    ...

    Session s2 = sf.openSession();
    ...
    s2.flush();
    s2.close();

    tx.commit();


    這是標(biāo)準(zhǔn)的使用JTA的代碼片斷,Transaction是跨Session的,它的生命周期比Session要長(zhǎng)。如果你在EJB中使用Hibernate,那么是最簡(jiǎn)單不過(guò)的了,你什么Transaction代碼統(tǒng)統(tǒng)都不要寫(xiě)了,直接在EJB的部署描述符上配置某某方法是否使用事務(wù)就可以了。

    現(xiàn)在我們來(lái)分析一下JTATransaction的源代碼, net.sf.hibernate.transaction.JTATransaction:

    public void begin(InitialContext context, ...
    ...
    ut = (UserTransaction) context.lookup(utName);
    ...


    看清楚了嗎? 和我上面寫(xiě)的代碼 tx = new Initial Context?().lookup("javax.transaction.UserTransaction"); 是不是完全一樣?

    public void commit() ...
    ...
    if (newTransaction) ut.commit();
    ...


    JTATransaction的控制稍微復(fù)雜,不過(guò)仍然可以很清楚的看出來(lái)Hibernate是如何封裝JTA的Transaction代碼的。

    但是你現(xiàn)在是否看到了什么問(wèn)題? 仔細(xì)想一下,Hibernate Transaction是從Session中獲得的,tx = session.beginTransaction(),最后要先提交tx,然后再session.close,這完全符合JDBC的Transaction的操作順序,但是這個(gè)順序是和JTA的Transactioin操作順序徹底矛盾的!!! JTA是先啟動(dòng)Transaction,然后啟動(dòng)Session,關(guān)閉Session,最后提交Transaction,因此當(dāng)你使用JTA的Transaction的時(shí)候,那么就千萬(wàn)不要使用Hibernate的Transaction,而是應(yīng)該像我上面的JTA的代碼片斷那樣使用才行。

    總結(jié):
    1、在JDBC上使用Hibernate

    必須寫(xiě)上Hibernate Transaction代碼,否則數(shù)據(jù)庫(kù)沒(méi)有反應(yīng)。此時(shí)Hibernate的Transaction就是Connection.commit而已

    2、在JTA上使用Hibernate

    寫(xiě)JTA的Transaction代碼,不要寫(xiě)Hibernate的Transaction代碼,否則程序會(huì)報(bào)錯(cuò)

    3、在EJB上使用Hibernate

    什么Transactioin代碼都不要寫(xiě),在EJB的部署描述符里面配置

    |---CMT(Container Managed Transaction)
    |
    |---BMT(Bean Managed Transaction)
    |
    |----JDBC Transaction
    |
    |----JTA Transaction

    ?


    ?

    ?


    ?

    關(guān)于session:

    1.? servlet的session機(jī)制基于cookies,關(guān)閉瀏覽器的cookies則session失效即不能用網(wǎng)站的登錄功能。

    2.? Hibernate Session.

    ????? 1>. session 清理緩存時(shí),按照以下順序執(zhí)行SQL語(yǔ)句:

    ??????????? session.save()的實(shí)體insert?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

    ??????????? 實(shí)體的update

    ??????????? 對(duì) 集合的delete

    ??????????? 集合元素的delete,update,insert

    ??????????? 集合的insert

    ????????????session.delete()的先后,執(zhí)行實(shí)體的delete

    ?????? 2>. 默認(rèn)時(shí),session在以下時(shí)間點(diǎn)清理緩存:

    ????????????? net.sf.hibernate.Transaction.commit():先清理緩存,再向數(shù)據(jù)庫(kù)提交事務(wù)??????????????????????????????????????????????????????????

    ????????????? Session.find()或iterate()時(shí),若緩存中持久化對(duì)象的屬性發(fā)生了變化,就會(huì)先清緩存,以保證查詢(xún)結(jié)果正確

    ?

    ?????? 3>.? Session的commit()和flush()的區(qū)別:flush()只執(zhí)行SQL語(yǔ)句,不提交事務(wù);commit()先調(diào)用flush(),再提交事務(wù)

    ?????? 4>.? Session.setFlushMode()用于設(shè)定清理緩存的時(shí)間點(diǎn)。

    清理緩存的模式 Session的查詢(xún)方法 Session.commit() Session.flush()
    FlushMode.AUTO 清理 清理 清理
    FlushMode.COMMIT 不清理 清理 清理
    FlushMode.NEVER 不清理 不清理 清理

    ???????????



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=797399

    posted on 2006-12-11 19:32 蘆葦 閱讀(1049) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): 數(shù)據(jù)庫(kù)JAVAHibernate
    主站蜘蛛池模板: 美女露隐私全部免费直播| 久久亚洲中文字幕无码| 亚洲一区中文字幕在线观看| 亚洲午夜电影在线观看高清| 亚洲精品无码久久久久A片苍井空| 美女尿口扒开图片免费| 巨胸喷奶水视频www免费视频| 久久久久久AV无码免费网站下载| 免费看片在线观看| 国产美女无遮挡免费视频| 国产亚洲精品不卡在线| 亚洲最大福利视频网站| 国产成人人综合亚洲欧美丁香花 | 亚洲高清在线视频| 亚洲国产成人精品无码区在线网站 | 亚洲处破女AV日韩精品| 亚洲AV综合色区无码二区爱AV| 国产精品亚洲精品久久精品| 在线涩涩免费观看国产精品| 中文字幕人成无码免费视频| 亚洲成a人片在线观看日本麻豆| 亚洲欧洲在线观看| 亚洲第一成年免费网站| 大地资源在线资源免费观看| 野花高清在线电影观看免费视频 | 精品免费久久久久国产一区 | 成人毛片免费视频| 无码精品人妻一区二区三区免费 | 两个人看的www免费视频| 国产电影午夜成年免费视频| 免费中文字幕一级毛片| 亚洲色图在线观看| 国产亚洲情侣久久精品| 亚洲免费在线观看视频| 国产成人高清亚洲| 亚洲一区精彩视频| 国产拍拍拍无码视频免费| 国产自产拍精品视频免费看| 亚洲精品在线播放视频| 精品国产免费一区二区三区| 麻豆国产VA免费精品高清在线|