# MySQL深度实战:从架构原理到生产级性能优化
## 目录
1. [MySQL核心架构与存储引擎](#1-mysql核心架构与存储引擎)
2. [设计模式在MySQL客户端中的应用](#2-设计模式在mysql客户端中的应用)
3. [Java反射机制实现ORM映射](#3-java反射机制实现orm映射)
4. [自定义注解实现SQL操作](#4-自定义注解实现sql操作)
5. [MySQL性能优化与JVM调优](#5-mysql性能优化与jvm调优)
6. [生产级数据库工具类实现](#6-生产级数据库工具类实现)
7. [数据库连接池优化](#7-数据库连接池优化)
8. [分库分表方案实现](#8-分库分表方案实现)
9. [读写分离与主从同步](#9-读写分离与主从同步)
10. [完整使用示例](#10-完整使用示例)
---
## 1. MySQL核心架构与存储引擎
### 1.1 MySQL架构分层
MySQL采用分层架构设计,从上到下分为连接层、服务层、引擎层和存储层。
```java
/**
* MySQL架构分层模拟
* 展示MySQL的核心架构组件
*/
public class MySQLArchitecture {
/**
* 连接层 - 负责客户端连接、身份认证、线程管理
*/
public static class ConnectionLayer {
// 连接池管理
private ConnectionPool connectionPool;
// 线程池管理
private ThreadPool threadPool;
/**
* 处理客户端连接请求
*/
public void handleConnection(ClientConnection client) {
// 1. 身份认证
authenticate(client);
// 2. 分配线程
Thread thread = threadPool.allocateThread(client);
// 3. 建立会话
Session session = createSession(client, thread);
// 4. 进入服务层处理
ServiceLayer serviceLayer = new ServiceLayer(session);
serviceLayer.processQueries();
}
private void authenticate(ClientConnection client) {
// 验证用户名、密码、主机权限
}
private Session createSession(ClientConnection client, Thread thread) {
return new Session(client, thread);
}
}
/**
* 服务层 - 核心功能层
*/
public static class ServiceLayer {
private Session session;
// SQL接口
private SQLInterface sqlInterface;
// 解析器
private Parser parser;
// 优化器
private Optimizer optimizer;
// 缓存
private QueryCache queryCache;
// 权限管理
private PrivilegeManager privilegeManager;
public ServiceLayer(Session session) {
this.session = session;
}
/**
* 处理查询请求
*/
public void processQueries() {
while (session.isConnected()) {
String sql = session.receiveQuery();
// 1. 检查查询缓存
QueryResult cachedResult = queryCache.get(sql);
if (cachedResult != null) {
session.sendResult(cachedResult);
continue;
}
// 2. 解析SQL
ParseTree parseTree = parser.parse(sql);
// 3. 权限检查
if (!privilegeManager.checkPrivilege(session, parseTree)) {
session.sendError("权限不足");
continue;
}
// 4. 查询优化
ExecutionPlan executionPlan = optimizer.optimize(parseTree);
// 5. 执行查询
EngineLayer engineLayer = new EngineLayer(executionPlan);
QueryResult result = engineLayer.execute();
// 6. 缓存查询结果
queryCache.put(sql, result);
// 7. 返回结果
session.sendResult(result);
}
}
}
/**
* 引擎层 - 插件式存储引擎
*/
public static class EngineLayer {
private ExecutionPlan executionPlan;
public EngineLayer(ExecutionPlan executionPlan) {
this.executionPlan = executionPlan;
}
/**
* 执行查询(选择合适的存储引擎)
*/
public QueryResult execute() {
String engineName = executionPlan.getEngineName();
// 工厂模式:根据引擎名称创建对应的引擎实例
StorageEngine engine = StorageEngineFactory.create(engineName);
return engine.execute(executionPlan);
}
}
/**
* 存储引擎工厂 - 工厂模式
*/
public static class StorageEngineFactory {
public static StorageEngine create(String engineName) {
switch (engineName.toLowerCase()) {
case "innodb":
return new InnoDBEngine();
case "myisam":
return new MyISAMEngine();
case "memory":
return new MemoryEngine();
case "csv":
return new CSVEngine();
default:
throw new IllegalArgumentException("不支持的存储引擎: " + engineName);
}
}
}
/**
* 存储引擎接口
*/
public interface StorageEngine {
QueryResult execute(ExecutionPlan plan);
Transaction beginTransaction();
Index createIndex(IndexDefinition definition);
}
/**
* InnoDB引擎实现(支持事务、行锁、外键)
*/
public static class InnoDBEngine implements StorageEngine {
// 缓冲池
private BufferPool bufferPool;
// 重做日志
private RedoLog redoLog;
// 回滚日志
private UndoLog undoLog;
@Override
public QueryResult execute(ExecutionPlan plan) {
// 1. 事务管理
Transaction transaction = beginTransaction();
try {
// 2. MVCC多版本并发控制
QueryResult result = executeWithMVCC(plan, transaction);
// 3. 提交事务
transaction.commit();
return result;
} catch (Exception e) {
transaction.rollback();
throw e;
}
}
private QueryResult executeWithMVCC(ExecutionPlan plan, Transaction transaction) {
// 实现MVCC逻辑
return new QueryResult();
}
@Override
public Transaction beginTransaction() {
return new InnoDBTransaction();
}
@Override
public Index createIndex(IndexDefinition definition) {
// InnoDB使用B+树索引
return new BPlusTreeIndex(definition);
}
}
/**
* MyISAM引擎实现(不支持事务、表锁、快速读取)
*/
public static class MyISAMEngine implements StorageEngine {
// 数据文件
private DataFile dataFile;
// 索引文件
private IndexFile indexFile;
@Override
public QueryResult execute(ExecutionPlan plan) {
// MyISAM不支持事务
return executeDirect(plan);
}
private QueryResult executeDirect(ExecutionPlan plan) {
// 直接执行查询
return new QueryResult();
}
@Override
public Transaction beginTransaction() {
throw new UnsupportedOperationException("MyISAM不支持事务");
}
@Override
public Index createIndex(IndexDefinition definition) {
// MyISAM也使用B+树索引
return new BPlusTreeIndex(definition);
}
}
/**
* 内存引擎实现(数据存储在内存,速度极快)
*/
public static class MemoryEngine implements StorageEngine {
private Map> tables = new ConcurrentHashMap<>();
@Override
public QueryResult execute(ExecutionPlan plan) {
// 从内存表读取数据
String tableName = plan.getTableName();
Map table = tables.get(tableName);
QueryResult result = new QueryResult();
result.setData(table.values());
return result;
}
@Override
public Transaction beginTransaction() {
// Memory引擎支持有限的事务
return new MemoryTransaction();
}
@Override
public Index createIndex(IndexDefinition definition) {
// Memory引擎使用Hash索引
return new HashIndex(definition);
}
}
/**
* CSV引擎实现(数据以CSV格式存储)
*/
public static class CSVEngine implements StorageEngine {
@Override
public QueryResult execute(ExecutionPlan plan) {
// 读取CSV文件
return new QueryResult();
}
@Override
public Transaction beginTransaction() {
throw new UnsupportedOperationException("CSV引擎不支持事务");
}
@Override
public Index createIndex(IndexDefinition definition) {
throw new UnsupportedOperationException("CSV引擎不支持索引");
}
}
}
```
### 1.2 InnoDB存储引擎核心特性
```java
/**
* InnoDB存储引擎核心特性实现
*/
public class InnoDBEngineFeatures {
/**
* MVCC多版本并发控制
*/
public static class MVCC {
// 事务ID生成器
private AtomicLong transactionIdGenerator = new AtomicLong(0);
// 活跃事务列表
private Set activeTransactions = new ConcurrentHashMap().keySet(Boolean.TRUE);
/**
* 生成新的事务ID
*/
public long beginTransaction() {
long txId = transactionIdGenerator.incrementAndGet();
activeTransactions.add(txId);
return txId;
}
/**
* 提交事务
*/
public void commitTransaction(long txId) {
activeTransactions.remove(txId);
// 清理过期版本
purgeOldVersions();
}
/**
* 读取数据快照(Read View)
*/
public ReadView createReadView(long txId) {
return new ReadView(txId, new ArrayList<>(activeTransactions));
}
/**
* 判断数据是否对当前事务可见
*/
public boolean isVisible(DataVersion dataVersion, ReadView readView) {
long dataTxId = dataVersion.getTransactionId();
// 数据是在当前事务创建的
if (dataTxId == readView.getTransactionId()) {
return true;
}
// 数据是在当前事务开始之前创建的
if (dataTxId < readView.getMinActiveTransactionId()) {
return true;
}
// 数据是在当前事务开始之后创建的,检查是否已提交
return !readView.getActiveTransactionIds().contains(dataTxId);
}
private void purgeOldVersions() {
// 清理不再需要的历史版本
}
}
/**
* 读视图
*/
public static class ReadView {
private final long transactionId;
private final List activeTransactionIds;
private final long minActiveTransactionId;
private final long maxActiveTransactionId;
public ReadView(long transactionId, List activeTransactionIds) {
this.transactionId = transactionId;
this.activeTransactionIds = activeTransactionIds;
this.minActiveTransactionId = activeTransactionIds.stream()
.min(Long::compare).orElse(0L);
this.maxActiveTransactionId = activeTransactionIds.stream()
.max(Long::compare).orElse(0L);
}
public long getTransactionId() {
return transactionId;
}
public List getActiveTransactionIds() {
return activeTransactionIds;
}
public long getMinActiveTransactionId() {
return minActiveTransactionId;
}
public long getMaxActiveTransactionId() {
return maxActiveTransactionId;
}
}
/**
* 数据版本
*/
public static class DataVersion {
private long transactionId;
private byte[] data;
private DataVersion nextVersion; // 链表指向下一个版本
public DataVersion(long transactionId, byte[] data) {
this.transactionId = transactionId;
this.data = data;
}
public long getTransactionId() {
return transactionId;
}
public byte[] getData() {
return data;
}
public DataVersion getNextVersion() {
return nextVersion;
}
public void setNextVersion(DataVersion nextVersion) {
this.nextVersion = nextVersion;
}
}
/**
* 缓冲池
*/
public static class BufferPool {
// 缓冲池大小(页)
private final int poolSize;
// LRU链表
private final ConcurrentLinkedDeque lruList;
// 哈希表(快速查找)
private final ConcurrentHashMap pageMap;
// 脏页列表
private final ConcurrentLinkedQueue dirtyPages;
public BufferPool(int poolSize) {
this.poolSize = poolSize;
this.lruList = new ConcurrentLinkedDeque<>();
this.pageMap = new ConcurrentHashMap<>();
this.dirtyPages = new ConcurrentLinkedQueue<>();
}
/**
* 从缓冲池获取页
*/
public BufferPage getPage(String tableSpace, long pageNumber) {
String key = tableSpace + ":" + pageNumber;
BufferPage page = pageMap.get(key);
if (page != null) {
// 更新LRU
lruList.remove(page);
lruList.addLast(page);
return page;
}
// 从磁盘加载
page = loadFromDisk(tableSpace, pageNumber);
// 如果缓冲池已满,执行淘汰策略
if (pageMap.size() >= poolSize) {
evictPage();
}
// 添加到缓冲池
pageMap.put(key, page);
lruList.addLast(page);
return page;
}
/**
* 脏页淘汰策略
*/
private void evictPage() {
// 优先淘汰非脏页
Iterator iterator = lruList.iterator();
while (iterator.hasNext()) {
BufferPage page = iterator.next();
if (!page.isDirty()) {
iterator.remove();
pageMap.remove(page.getKey());
return;
}
}
// 如果都是脏页,刷新并淘汰最旧的脏页
BufferPage oldestDirty = lruList.pollFirst();
if (oldestDirty != null) {
flushPage(oldestDirty);
pageMap.remove(oldestDirty.getKey());
}
}
/**
* 标记页为脏页
*/
public void markDirty(BufferPage page) {
page.setDirty(true);
dirtyPages.add(page);
}
/**
* 刷新脏页到磁盘
*/
public void flushDirtyPages() {
BufferPage page;
while ((page = dirtyPages.poll()) != null) {
flushPage(page);
}
}
private BufferPage loadFromDisk(String tableSpace, long pageNumber) {
// 模拟从磁盘加载页
return new BufferPage(tableSpace, pageNumber);
}
private void flushPage(BufferPage page) {
// 模拟刷新页到磁盘
page.setDirty(false);
}
}
/**
* 缓冲页
*/
public static class BufferPage {
private String tableSpace;
private long pageNumber;
private byte[] data;
private boolean dirty;
private long lastAccessTime;
public BufferPage(String tableSpace, long pageNumber) {
this.tableSpace = tableSpace;
this.pageNumber = pageNumber;
this.data = new byte[16 * 1024]; // 16KB页
this.dirty = false;
this.lastAccessTime = System.currentTimeMillis();
}
public String getKey() {
return tableSpace + ":" + pageNumber;
}
public byte[] getData() {
this.lastAccessTime = System.currentTimeMillis();
return data;
}
public void setData(byte[] data) {
this.data = data;
}
public boolean isDirty() {
return dirty;
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
public long getLastAccessTime() {
return lastAccessTime;
}
}
/**
* B+树索引
*/
public static class BPlusTreeIndex {
private Node root;
private int order; // B+树的阶
public BPlusTreeIndex(int order) {
this.order = order;
this.root = new LeafNode();
}
/**
* 插入键值对
*/
public void insert(long key, RowLocation location) {
root.insert(key, location);
// 如果根节点分裂,创建新的根节点
if (root.isOverflow()) {
InternalNode newRoot = new InternalNode();
newRoot.children.add(root);
newRoot.splitChild(0);
root = newRoot;
}
}
/**
* 查询键对应的位置
*/
public RowLocation search(long key) {
return root.search(key);
}
/**
* 范围查询
*/
public List rangeSearch(long minKey, long maxKey) {
return root.rangeSearch(minKey, maxKey);
}
/**
* B+树节点基类
*/
public abstract class Node {
protected List keys = new ArrayList<>();
public abstract RowLocation search(long key);
public abstract List rangeSearch(long minKey, long maxKey);
public abstract void insert(long key, RowLocation location);
public abstract boolean isOverflow();
public abstract boolean isUnderflow();
}
/**
* 内部节点
*/
public class InternalNode extends Node {
protected List children = new ArrayList<>();
@Override
public RowLocation search(long key) {
int index = findChildIndex(key);
return children.get(index).search(key);
}
@Override
public List rangeSearch(long minKey, long maxKey) {
int start = findChildIndex(minKey);
List results = new ArrayList<>();
for (int i = start; i < children.size(); i++) {
results.addAll(children.get(i).rangeSearch(minKey, maxKey));
}
return results;
}
@Override
public void insert(long key, RowLocation location) {
int index = findChildIndex(key);
children.get(index).insert(key, location);
}
@Override
public boolean isOverflow() {
return children.size() > order;
}
@Override
public boolean isUnderflow() {
return children.size() < (order + 1) / 2;
}
private int findChildIndex(long key) {
int i = 0;
while (i < keys.size() && key >= keys.get(i)) {
i++;
}
return i;
}
public void splitChild(int index) {
Node child = children.get(index);
InternalNode newNode = new InternalNode();
int mid = child.keys.size() / 2;
// 分裂键
long splitKey = child.keys.get(mid);
// 分裂子节点
for (int i = mid + 1; i < child.keys.size(); i++) {
newNode.keys.add(child.keys.get(i));
newNode.children.add(((InternalNode) child).children.get(i));
}
newNode.children.add(((InternalNode) child).children.get(child.keys.size()));
// 调整原节点
child.keys.subList(mid, child.keys.size()).clear();
((InternalNode) child).children.subList(mid + 1, ((InternalNode) child).children.size()).clear();
// 插入新节点和分割键
keys.add(index, splitKey);
children.add(index + 1, newNode);
}
}
/**
* 叶子节点
*/
public class LeafNode extends Node {
protected List locations = new ArrayList<>();
protected LeafNode next;
@Override
public RowLocation search(long key) {
int index = Collections.binarySearch(keys, key);
if (index >= 0) {
return locations.get(index);
}
return null;
}
@Override
public List rangeSearch(long minKey, long maxKey) {
List results = new ArrayList<>();
for (int i = 0; i < keys.size(); i++) {
if (keys.get(i) >= minKey && keys.get(i) <= maxKey) {
results.add(locations.get(i));
} else if (keys.get(i) > maxKey) {
break;
}
}
// 检查下一个叶子节点
if (next != null) {
results.addAll(next.rangeSearch(minKey, maxKey));
}
return results;
}
@Override
public void insert(long key, RowLocation location) {
int index = Collections.binarySearch(keys, key);
if (index < 0) {
index = -index - 1;
}
keys.add(index, key);
locations.add(index, location);
}
@Override
public boolean isOverflow() {
return keys.size() > order;
}
@Override
public boolean isUnderflow() {
return keys.size() < order / 2;
}
}
}
/**
* 行位置
*/
public static class RowLocation {
private long pageNumber;
private int offset;
public RowLocation(long pageNumber, int offset) {
this.pageNumber = pageNumber;
this.offset = offset;
}
public long getPageNumber() {
return pageNumber;
}
public int getOffset() {
return offset;
}
}
}
```
---
## 2. 设计模式在MySQL客户端中的应用
### 2.1 单例模式 - 数据库连接池管理
```java
/**
* 数据库连接池 - 单例模式
* 确保全局只有一个连接池实例
*/
public class DBConnectionPool {
// 饿汉式单例
private static final DBConnectionPool INSTANCE = new DBConnectionPool();
// 连接池配置
private HikariDataSource dataSource;
private final HikariConfig poolConfig;
/**
* 私有构造函数
*/
private DBConnectionPool() {
this.poolConfig = new HikariConfig();
initializePoolConfig();
}
/**
* 获取单例实例
*/
public static DBConnectionPool getInstance() {
return INSTANCE;
}
/**
* 初始化连接池配置
*/
private void initializePoolConfig() {
// 连接池基本配置
poolConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 连接池大小配置
poolConfig.setMaximumPoolSize(200); // 最大连接数
poolConfig.setMinimumIdle(20); // 最小空闲连接数
poolConfig.setIdleTimeout(600000); // 空闲超时时间(10分钟)
poolConfig.setMaxLifetime(1800000); // 连接最大生命周期(30分钟)
poolConfig.setConnectionTimeout(30000); // 获取连接超时时间(30秒)
// 连接测试配置
poolConfig.setConnectionTestQuery("SELECT 1");
poolConfig.setValidationTimeout(5000);
// 泄漏检测配置
poolConfig.setLeakDetectionThreshold(60000); // 连接泄漏检测阈值(1分钟)
// 性能优化配置
poolConfig.addDataSourceProperty("cachePrepStmts", "true"); // 缓存PreparedStatement
poolConfig.addDataSourceProperty("prepStmtCacheSize", "250"); // 缓存大小
poolConfig.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); // 缓存SQL长度限制
poolConfig.addDataSourceProperty("useServerPrepStmts", "true"); // 使用服务端PreparedStatement
poolConfig.addDataSourceProperty("useLocalSessionState", "true");
poolConfig.addDataSourceProperty("rewriteBatchedStatements", "true"); // 批量语句重写
poolConfig.addDataSourceProperty("cacheResultSetMetadata", "true");
poolConfig.addDataSourceProperty("cacheServerConfiguration", "true");
poolConfig.addDataSourceProperty("elideSetAutoCommits", "true");
poolConfig.addDataSourceProperty("maintainTimeStats", "false");
// 时区配置
poolConfig.addDataSourceProperty("serverTimezone", "Asia/Shanghai");
}
/**
* 初始化连接池
*/
public synchronized void init(String url, String username, String password) {
if (dataSource != null && !dataSource.isClosed()) {
return;
}
poolConfig.setJdbcUrl(url);
poolConfig.setUsername(username);
poolConfig.setPassword(password);
dataSource = new HikariDataSource(poolConfig);
System.out.println("数据库连接池初始化成功");
}
/**
* 获取数据库连接
*/
public Connection getConnection() throws SQLException {
if (dataSource == null) {
throw new IllegalStateException("连接池未初始化");
}
return dataSource.getConnection();
}
/**
* 关闭连接池
*/
public synchronized void close() {
if (dataSource != null && !dataSource.isClosed()) {
dataSource.close();
System.out.println("数据库连接池已关闭");
}
}
/**
* 获取连接池状态
*/
public Map getPoolStats() {
Map stats = new HashMap<>();
if (dataSource != null) {
HikariPoolMXBean poolProxy = dataSource.getHikariPoolMXBean();
stats.put("activeConnections", poolProxy.getActiveConnections());
stats.put("idleConnections", poolProxy.getIdleConnections());
stats.put("totalConnections", poolProxy.getTotalConnections());
stats.put("threadsAwaitingConnection", poolProxy.getThreadsAwaitingConnection());
}
return stats;
}
}
```
### 2.2 工厂模式 - SQL构建器工厂
```java
/**
* SQL构建器工厂 - 工厂模式
* 根据不同类型创建对应的SQL构建器
*/
public class SQLBuilderFactory {
/**
* SQL类型枚举
*/
public enum SQLType {
SELECT,
INSERT,
UPDATE,
DELETE,
COUNT,
SUM,
AVG,
MAX,
MIN
}
/**
* 工厂方法:创建SQL构建器
*/
public static SQLBuilder create(SQLType type) {
switch (type) {
case SELECT:
return new SelectBuilder();
case INSERT:
return new InsertBuilder();
case UPDATE:
return new UpdateBuilder();
case DELETE:
return new DeleteBuilder();
case COUNT:
return new CountBuilder();
case SUM:
return new AggregateBuilder("SUM");
case AVG:
return new AggregateBuilder("AVG");
case MAX:
return new AggregateBuilder("MAX");
case MIN:
return new AggregateBuilder("MIN");
default:
throw new IllegalArgumentException("不支持的SQL类型: " + type);
}
}
/**
* SQL构建器接口
*/
public interface SQLBuilder {
SQLBuilder table(String table);
String build();
}
/**
* SELECT构建器
*/
public static class SelectBuilder implements SQLBuilder {
private StringBuilder sql = new StringBuilder("SELECT ");
private boolean distinct = false;
private List columns = new ArrayList<>();
private String table;
private List whereConditions = new ArrayList<>();
private List groupByFields = new ArrayList<>();
private List orderByFields = new ArrayList<>();
private Integer limit;
private Integer offset;
public SelectBuilder distinct() {
this.distinct = true;
return this;
}
public SelectBuilder columns(String... cols) {
Collections.addAll(this.columns, cols);
return this;
}
public SelectBuilder column(String col) {
this.columns.add(col);
return this;
}
public SelectBuilder where(String condition) {
this.whereConditions.add(condition);
return this;
}
public SelectBuilder where(String field, Object value) {
this.whereConditions.add(field + " = " + formatValue(value));
return this;
}
public SelectBuilder groupBy(String field) {
this.groupByFields.add(field);
return this;
}
public SelectBuilder orderBy(String field) {
this.orderByFields.add(field + " ASC");
return this;
}
public SelectBuilder orderByDesc(String field) {
this.orderByFields.add(field + " DESC");
return this;
}
public SelectBuilder limit(int limit) {
this.limit = limit;
return this;
}
public SelectBuilder offset(int offset) {
this.offset = offset;
return this;
}
@Override
public SelectBuilder table(String table) {
this.table = table;
return this;
}
@Override
public String build() {
if (distinct) {
sql.append("DISTINCT ");
}
// 处理列
if (columns.isEmpty()) {
sql.append("*");
} else {
sql.append(String.join(", ", columns));
}
// 处理表
sql.append(" FROM ").append(table);
// 处理WHERE条件
if (!whereConditions.isEmpty()) {
sql.append(" WHERE ").append(String.join(" AND ", whereConditions));
}
// 处理GROUP BY
if (!groupByFields.isEmpty()) {
sql.append(" GROUP BY ").append(String.join(", ", groupByFields));
}
// 处理ORDER BY
if (!orderByFields.isEmpty()) {
sql.append(" ORDER BY ").append(String.join(", ", orderByFields));
}
// 处理LIMIT和OFFSET
if (limit != null) {
sql.append(" LIMIT ").append(limit);
if (offset != null) {
sql.append(" OFFSET ").append(offset);
}
}
return sql.toString();
}
private String formatValue(Object value) {
if (value == null) {
return "NULL";
} else if (value instanceof String) {
return "'" + value + "'";
} else if (value instanceof Date) {
return "'" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(value) + "'";
} else {
return String.valueOf(value);
}
}
}
/**
* INSERT构建器
*/
public static class InsertBuilder implements SQLBuilder {
private String table;
private List columns = new ArrayList<>();
private List