Hibernate配置Mysql和Oracle雙數(shù)據(jù)源

1.借鑒:

? ? ? ? ?hibernate配置多個(gè)數(shù)據(jù)源及事物(以兩個(gè)數(shù)據(jù)源為例)

? ? ? ??Hibernate學(xué)習(xí)記錄3 Hibernate 配置多數(shù)據(jù)源? ??

? ? ? ? 百度和谷歌了很多,最終參看以上兩個(gè)鏈接,再次感謝。

2.開始:

? ? ? ?2.1 首先需要搞一個(gè)spring4+hibernate4的環(huán)境,同時(shí)配置Mysql和Oracle的驅(qū)動(dòng),連接池等信息,使用maven快速構(gòu)建,這里就粘貼一下pom下的關(guān)鍵配置

1
2
3

2.2 接下來是applicationContext.xml文件的內(nèi)容.

4

2.3 jdbc.properties中的配置

5

2.4接下來是applicationContext-hibernate.xml文件的內(nèi)容

兩個(gè)數(shù)據(jù)庫,兩套數(shù)據(jù)庫方言,所以需要兩套DataSource, SessionFactory,事物管理

2.4.1首先是mysql

? ? mysql的DataSource

mysql-DataSource

mysql的SessionFactory

mysql-SessionFactory

mysql-事務(wù)管理器和編制aop

mysql-事物

接下來是mysql的切面【這里同時(shí)配置了Oracle的切面】

mysql-切面

2.4.2接下來是Oracle

? ? Oracle的DataSource

Oracle-DataSource

? ?Oracle的SessionFactory

Oracle-SessionFactory

Oracle是事務(wù)管理器和編制aop

Oracle-事物管理

Oracle的切面【沒錯(cuò),就是上面那張圖,ctrl+c,v來的】

Oracle-切面

至此,配置部分已經(jīng)完成了。

2.5 好的,接下來編寫我們自己的偽SessionFactory,姑且就叫HibernateSessionFactory吧

? ? ? ? ? ?代碼很少也很簡單,名稱注入配置的兩個(gè)SessionFactory,并聲明組件,唯一需要注意的是得讓spring掃描的到。

@Component

public class HibernateSessionFactory

{

? ? @Resource(name = "sessionFactory_mysql")

? ? SessionFactory sessionFactoryMysql;

? ? @Resource(name = "sessionFactory_oracle")

? ? SessionFactory sessionFactoryOracle;

? ? public HibernateSessionFactory()

? ?{

? ?}

? ? public SessionFactory getSessionFactoryMysql()

? ? {

? ? ? ? return sessionFactoryMysql;

? ? ?}

? ? public SessionFactory getSessionFactoryOracle()

? ? {

? ? ? ? return sessionFactoryOracle;

? ? }

}

2.6接下來是BaseDao

public interface BaseDao

{

? ? /***

? ? * 保存對(duì)象

? ? * @param entity

? ? */

? ? int insert(T entity);

? ? /**

? ? * 更新對(duì)象

? ? * @param entity

? ? */

? ? int update(T entity);

? ? /***

? ? * 根據(jù)主鍵刪除

? ? * @param id

? ? * @return

? ? */

? ? int deleteById(Serializable id);

? ? /***

? ? * 刪除

? ? * @param entity

? ? * @return

? ? */

? ? int delete(T entity);

? ? /***

? ? * 通過id刪除

? ? * @param id

? ? * @return

? ? */

? ? T selectById(Serializable id);

? ? /***

? ? * 查詢?nèi)?/p>

? ? * @return

? ? */

? ? Collection selectAll();

? ? /***

? ? * 通過hql查詢

? ? * @param hql

? ? * @param params

? ? * @return

? ? */

? ? Collection selectByHql(String hql, Object[] params);

? ? /***

? ? * 原生sql查詢

? ? * @param sql

? ? * @param params

? ? * @return

? ? */

? ? Collection selectByNativeSql(String sql, Object[] params);

? ? /***

? ? * 原生sql查詢

? ? * @param sql

? ? * @param params

? ? * @return

? ? */

? ? Collection selectByNativeSql(String sql, LinkedList params);

? ? /***

? ? * 原生sql查詢

? ? * @param sql

? ? * @param params

? ? * @return

? ? */

? ? List selectByNativeSql(String sql, LinkedList params, Class clazz);

? ? /**

? ? * 分頁查詢

? ? * @param hql

? ? * @param pageNo

? ? * @param pageSize

? ? * @return

? ? */

? ? Collection selectByPage(String hql, int pageNo, int pageSize);

? ? /***

? ? * 分頁查詢

? ? * @param params

? ? * @param pageNo

? ? * @param pageSize

? ? * @return

? ? */

? ? PageInfo> selectByPage(String hql, LinkedList params, int pageNo, int pageSize);

? ? /***

? ? * 通過sql分頁查詢

? ? * @param sql

? ? * @param params

? ? * @param clazz

? ? * @param pageNo

? ? * @param pageSize

? ? * @return

? ? */

? ? PageInfo selectByNativeSqlAndPage(String sql, LinkedList params, Class clazz, int pageNo, int pageSize);

}

可以看到的PageInfo自定義如下,并不是mybatis-pagerhelper插件里面的。get和set方法就不寫了。

public class PageInfo implements Serializable

{

? ? private int pageNumber;

? ? private int pageSize;

? ? private int total;

? ? private T datas;

? ? public PageInfo()

{

}

? ? public PageInfo(int pageNumber,

? ? ? ? ? ? ? ? ? ? int pageSize,

? ? ? ? ? ? ? ? ? ? int total,

? ? ? ? ? ? ? ? ? ? T datas)

{

? ? ? ? this.pageNumber = pageNumber;

? ? ? ? this.pageSize = pageSize;

? ? ? ? this.total = total;

? ? ? ? this.datas = datas;

? ? }

}

2.7 接下來是BaseDaoImpl,重點(diǎn)看下代碼最后面的getSessionFactory方法,這里直接返回null,為啥不寫在BaseDao中呢,其實(shí)都可以。

/***

* CREATED BY: kaiser

*? ? ? DATE: 2018/5/27

*? ? ? INFO: 子類必須重寫getSessionFactory方法

*/

public class BaseDaoImpl implements BaseDao

{

? ? private Class clazz;

? ? @Autowired

? ? HibernateSessionFactory sessionFactory;

? ? @SuppressWarnings("unchecked")

? ? public BaseDaoImpl()

? ? {

? ? ? ? ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();

? ? ? ? Type[] actualTypeArguments = type.getActualTypeArguments();

? ? ? ? clazz = (Class) type.getActualTypeArguments()[0];

? ? }

? ? @Override

? ? public int insert(T entity)

? ? {

? ? ? ? getSessionFactory().getCurrentSession().save(entity);

? ? ? ? return 0;

? ? }

? ? @Override

? ? public int update(T entity)

? ? {

? ? ? ? getSessionFactory().getCurrentSession().update(entity);

? ? ? ? return 0;

? ? }

? ? @Override

? ? public int deleteById(Serializable id)

? ? {

? ? ? ? T entity = selectById(id);

? ? ? ? getSessionFactory().getCurrentSession().delete(entity);

? ? ? ? return 0;

? ? }

? ? @Override

? ? public int delete(T entity)

? ? {

? ? ? ? getSessionFactory().getCurrentSession().delete(entity);

? ? ? ? return 0;

? ? }

? ? @SuppressWarnings("unchecked")

? ? @Override

? ? public T selectById(Serializable id)

? ? {

? ? ? ? return (T) getSessionFactory().getCurrentSession().get(clazz, id);

? ? }

? ? @Override

? ? public Collection selectAll()

? ? {

//? ? ? ? return sessionFactory.getCurrentSession().createQuery("from ")

? ? ? ? this.getClazzName();

? ? ? ? return null;

? ? }

? ? @SuppressWarnings("unchecked")

? ? @Override

? ? public Collection selectByHql(String hql,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Object[] params)

? ? {

? ? ? ? Query query = getSessionFactory().getCurrentSession()

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .createQuery(hql);

? ? ? ? if (params != null)

? ? ? ? {

? ? ? ? ? ? for(int i = 0; i < params.length; i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? query.setParameter(i, params[i]);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return query.list();

? ? }

? ? @SuppressWarnings("unchecked")

? ? @Override

? ? public List selectByNativeSql(String sql,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Object[] params)

? ? {

? ? ? ? Query query = getSessionFactory().getCurrentSession()

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .createSQLQuery(sql);

? ? ? ? if (params != null)

? ? ? ? {

? ? ? ? ? ? for(int i = 0; i < params.length; i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? query.setParameter(i, params[i]);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return query.list();

? ? }

? ? @SuppressWarnings("unchecked")

? ? @Override

? ? public Collection selectByNativeSql(String sql,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LinkedList params)

? ? {

? ? ? ? Query query = getSessionFactory().getCurrentSession().createSQLQuery(sql);

? ? ? ? if (params != null)

? ? ? ? {

? ? ? ? ? ? for(int i = 0; i < params.size(); i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? query.setParameter(i, params.get(i));

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return query.list();

? ? }

? ? @Override

? ? public List selectByNativeSql(String sql,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LinkedList params,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Class clazz)

? ? {

? ? ? ? SQLQuery query = getSessionFactory().getCurrentSession().createSQLQuery(sql);

? ? ? ? if (params != null)

? ? ? ? {

? ? ? ? ? ? for(int i = 0; i < params.size(); i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? query.setParameter(i, params.get(i));

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? query.addEntity(clazz);

? ? ? ? return query.list();

? ? }

? ? @SuppressWarnings("unchecked")

? ? @Override

? ? public Collection selectByPage(String hql,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int pageNo,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int pageSize)

? ? {

? ? ? ? return getSessionFactory().getCurrentSession().createQuery(hql)

? ? ? ? ? ? ? ? ? ? ? .setFirstResult((pageNo - 1) * pageSize)

? ? ? ? ? ? ? ? ? ? ? .setMaxResults(pageSize)

? ? ? ? ? ? ? ? ? ? ? .list();

? ? }

? ? @SuppressWarnings("unchecked")

? ? @Override

? ? public PageInfo> selectByPage(String hql,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LinkedList params,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int pageNo,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int pageSize)

? ? {

? ? ? ? Query query = getSessionFactory().getCurrentSession()

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .createQuery(hql);

? ? ? ? if (params != null)

? ? ? ? {

? ? ? ? ? ? for(int i = 0; i < params.size(); i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? query.setParameter(i, params.get(i));

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? ScrollableResults scroll = query.scroll();

? ? ? ? scroll.last();

? ? ? ? query.setFirstResult(pageNo);

? ? ? ? query.setMaxResults(pageSize);

? ? ? ? PageInfo> pageInfo = new PageInfo>(pageNo, pageSize, scroll.getRowNumber() + 1, query.list());

? ? ? ? return pageInfo;

? ? }

? ? @SuppressWarnings("unchecked")

? ? @Override

? ? public PageInfo selectByNativeSqlAndPage(String sql,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LinkedList params,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Class clazz,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int pageNo,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int pageSize)

? ? {

? ? ? ? Query query = getSessionFactory().getCurrentSession()

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .createSQLQuery(sql)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .addEntity(clazz);

? ? ? ? if (params != null)

? ? ? ? {

? ? ? ? ? ? for(int i = 0; i < params.size(); i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? query.setParameter(i, params.get(i));

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? ScrollableResults scroll = query.scroll();

? ? ? ? scroll.last();

? ? ? ? query.setFirstResult(pageNo);

? ? ? ? query.setMaxResults(pageSize);

? ? ? ? PageInfo pageInfo = new PageInfo(pageNo, pageSize, scroll.getRowNumber() + 1, query.list());

? ? ? ? return pageInfo;

? ? }

? ? private String getClazzName()

? ? {

? ? ? ? System.out.println(this.clazz.getName());

? ? ? ? return this.clazz.getName();

? ? }

? ? public void clearDataSourceType()

? ? {

? ? ? ? DataSourceContextHolder.clearDataSourceType();

? ? }

? ? protected SessionFactory getSessionFactory()

? ? {

? ? ? ? return null;

? ? }

}

2.8 接下來是實(shí)體類了

Result對(duì)應(yīng)的是mysql庫里面的表t_result。

注:Entity只是實(shí)現(xiàn)了Serializable接口,這里就不貼了

@Entity

@Table(name = "T_RESULT", schema = "ZSXY")

public class Result extends com.kaiser.domain.Entity

{

? ? /** 屬性映射字段 */

? ? @Id

? ? @GeneratedValue(generator = "id")

? ? @GenericGenerator(name = "id", strategy = "identity")

? ? @Column(name = "id")

? ? private int id;

? ? @Column(name = "session_id", nullable = false)

? ? private String sessionId;

? ? @Column(name = "query_info", nullable = true)

? ? private String queryInfo;

? ? @Column(name = "result_info", nullable = true)

? ? private String resultInfo;

? ? @Column(name = "order_id", columnDefinition = "varchar(32)")

? ? private String orderId;

? ? @Temporal(TemporalType.TIMESTAMP)

? ? @Column(name = "create_time")

? ? private Date createTime;

? ? @Column(name = "status")

? ? private String status;

? ? @Column(name = "task_id")

? ? private String taskId;

}

UserInfo對(duì)應(yīng)的是oracle庫里面的表t_user_info。

注:1.Entity只是實(shí)現(xiàn)了Serializable接口,這里不貼了

? ? ? ? 2.因?yàn)閠_user_info表沒有主鍵,所以得使用復(fù)合主鍵,否則會(huì)報(bào)錯(cuò)

@Entity

@Table(name = "T_USER_INFO",

? ? ? schema = "sms")

public class UserInfo extends com.kaiser.domain.Entity

{

? ? @EmbeddedId

? ? @AttributeOverrides({

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @AttributeOverride(name = "uid", column = @Column(name = "uiid")),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @AttributeOverride(name = "code", column = @Column(name = "ucode")),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @AttributeOverride(name = "account", column = @Column(name = "uaccount")),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @AttributeOverride(name = "password", column = @Column(name = "upassword"))

? ? ? ? ? ? ? ? ? ? ? ? })

? ? private UserInfoId userInfoId;

? ? @Column(name = "reg_type")

? ? private int registerType;

? ? @Column(name = "isactive")

? ? private String isActive;

? ? @Temporal(TemporalType.TIMESTAMP)

? ? @Column(name = "reg_date")

? ? private Date createTime;

? ? @Column(name = "aid")

? ? private int RoleId;

? ? @Column(name = "balance")

? ? private double balance;

}

? ? ? ? ? 這個(gè)是復(fù)合主鍵的實(shí)體類,必須重寫equals和hascode方法,同時(shí)必須注解@Embeddable以及一個(gè)無參的構(gòu)造方法。同時(shí)需要注意的是復(fù)合主鍵的實(shí)體類中定義的屬性列不能在原實(shí)體類【UserInfo】中重復(fù)定義,比如說UserInfoId中有uid屬性,在UserInfo中不需要定義。,之所以是【uid,code,account,password】四個(gè)屬性,完全是為了生成一個(gè)id,也可以

@Embeddable

public class UserInfoId implements Serializable

{

? ? @Column(name = "uid")

? ? private int id;

? ? @Column(name = "code")

? ? private String code;

? ? @Column(name = "account")

? ? private String account;

? ? @Column(name = "password")

? ? private String password;

? ? public UserInfoId() { }

? ? public UserInfoId(int id,

? ? ? ? ? ? ? ? ? ? ? String code,

? ? ? ? ? ? ? ? ? ? ? String account,

? ? ? ? ? ? ? ? ? ? ? String password)

? ? {

? ? ? ? this.id = id;

? ? ? ? this.code = code;

? ? ? ? this.account = account;

? ? ? ? this.password = password;

? ? }

? ? @Override

? ? public boolean equals(Object o)

? ? {

? ? ? ? if (this == o) { return true; }

? ? ? ? if (o == null || getClass() != o.getClass()) { return false; }

? ? ? ? UserInfoId that = (UserInfoId) o;

? ? ? ? return getId() == that.getId() && Objects.equals(getCode(),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? that.getCode()) && Objects.equals(getAccount(),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? that.getAccount()) &&

? ? ? ? ? ? ? ? Objects.equals(getPassword(),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? that.getPassword());

? ? }

? ? @Override

? ? public int hashCode()

? ? {

? ? ? ? return Objects.hash(getId(),

? ? ? ? ? ? ? ? ? ? ? ? ? ? getCode(),

? ? ? ? ? ? ? ? ? ? ? ? ? ? getAccount(),

? ? ? ? ? ? ? ? ? ? ? ? ? ? getPassword());

? ? }

}

2.9 接下來是Dao

public interface ResultDao<Result>?extends BaseDao<Result>{}

public interface UserInfoDao<UserInfo> extends BaseDao<UserInfo>{}

2.10 接著是DaoImpl

@Repository("resultDao")

public class ResultDaoImpl<Result> extends BaseDaoImpl<Result> implements ResultDao<Result>

{

? ? @Override

? ? protected SessionFactory getSessionFactory()

? ? {

? ? ? ? return sessionFactory.getSessionFactoryMysql();

? ? }

}

@Repository("userInfoDao")

public class UserInfoDaoImpl<UserInfo> extends BaseDaoImpl<UserInfo> implements UserInfoDao<UserInfo>

{

? ? @Override

? ? protected SessionFactory getSessionFactory()

? ? {

? ? ? ? return sessionFactory.getSessionFactoryOracle();

? ? }

}

2.11 BaseService?

public interface BaseService<T extends Entity<T>,? dao extends BaseDao<T>>

{

? ? /***

? ? * 保存

? ? * @param entity

? ? * @return

? ? */

? ? int save(T entity);

? ? /**

? ? * 更新

? ? * @param entity

? ? * @return

? ? */

? ? int renew(T entity);

? ? /***

? ? * 通過id刪除

? ? * @param id

? ? * @return

? ? */

? ? int dropById(Serializable id);

? ? /***

? ? * 刪除

? ? * @param entity

? ? * @return

? ? */

? ? int drop(T entity);

? ? /***

? ? * 通過id查找

? ? * @param id

? ? * @return

? ? */

? ? T findById(Serializable id);

? ? /***

? ? * 查詢?nèi)?/p>

? ? * @return

? ? */

? ? Collection findAll();

}

2.12 BaseServiceImpl

public class BaseServiceImpl<T extends Entity<T>,? Dao extends BaseDao<T>> implements BaseService<T, Dao>

{

? ? @Autowired

? ? protected Dao dao;

? ? @Override

? ? public int save(T entity)

? ? {

? ? ? ? return dao.insert(entity);

? ? }

? ? @Override

? ? public int renew(T entity)

? ? {

? ? ? ? return dao.update(entity);

? ? }

? ? @Override

? ? public int dropById(Serializable id)

? ? {

? ? ? ? return dao.deleteById(id);

? ? }

? ? @Override

? ? public int drop(T entity)

? ? {

? ? ? ? return dao.delete(entity);

? ? }

? ? @Override

? ? public T findById(Serializable id)

? ? {

? ? ? ? return dao.selectById(id);

? ? }

? ? @Override

? ? public Collection findAll()

? ? {

? ? ? ? return dao.selectAll();

? ? }

}

2.13 繼承自BaseService的類,這里以ResultService和ResultServiceImpl為例

public interface ResultService extends BaseService<Result, ResultDao<Result>>{}

@Service("resultService")

public class ResultServiceImpl extends BaseServiceImpl<Result, ResultDao<Result>> implements ResultService{}

2.14 接下來可以在Controller層使用注解注入使用了

3.大功告成

雖然寫完了,但是不確定的是這是不是最優(yōu)解,還希望能對(duì)碰上此問題的各位有所幫助,如果更好的方案,希望能不吝指教。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,766評(píng)論 18 399
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,835評(píng)論 0 11
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,947評(píng)論 18 139
  • 先創(chuàng)建服務(wù)端的APP 1.官網(wǎng)下載Winrun4j。http://winrun4j.sourceforge.net...
    Alex_1799閱讀 1,808評(píng)論 1 2
  • 傍晚去小區(qū)附近快餐店吃飯。拉開店門,看到一個(gè)十二三歲清純質(zhì)樸陽光大方的女孩,獨(dú)自坐在靠門的桌旁,等候用餐...
    丁香花開_2179閱讀 330評(píng)論 0 0