北京大学JAVA讲义-第九章-(续)_第1页
北京大学JAVA讲义-第九章-(续)_第2页
北京大学JAVA讲义-第九章-(续)_第3页
北京大学JAVA讲义-第九章-(续)_第4页
北京大学JAVA讲义-第九章-(续)_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java数据库编程(进阶篇)北京大学JAVA讲义第九章(续)|JDBC高级应用与最佳实践Contents课程目录Java数据库编程高级主题,涵盖JDBC进阶、连接池、DAO模式与安全实践。01JDBC进阶机制:批处理、事务与元数据02数据库连接池:原理、实现与性能优化03DAO设计模式:架构分层与工程实践04安全实践与综合案例CHAPTER01JDBC进阶机制批处理、事务管理与数据库元数据的深入掌握CHAPTER09·SQL&JDBCSQL与JDBC:回顾与衔接SQL作为数据操作的标准语言,通过JDBCAPI与Java应用实现桥接。掌握SQL四大类语句(DDL/DML/DCL/DQL)的分类逻辑,是理解JDBC中Statement与PreparedStatement分工的基础。DDL数据定义负责CREATE/ALTER/DROP表结构操作,对应JDBC中Statement.execute()方法执行execute()DML数据操作涵盖INSERT/UPDATE/DELETE,通过PreparedStatement预编译可防止SQL注入攻击PreparedStatementDQL数据查询以SELECT为核心,ResultSet对象逐行遍历返回结果,需注意游标方向与资源释放ResultSetDCL数据控制管理GRANT/REVOKE权限与事务COMMIT/ROLLBACK,对应JDBC的Connection事务控制方法ConnectionJDBC·核心流程JDBC标准开发流程(六步法回顾)JDBC开发遵循"加载驱动→获取连接→创建语句→执行操作→处理结果→释放资源"的标准化流程。进阶应用中的连接池、事务控制等机制,本质上是对第2步和第6步的优化与增强。01加载驱动Class.forName()注册数据库驱动,MySQL8.0+使用com.mysql.cj.jdbc.Driver,仅需执行一次CLASS.FORNAME02获取连接DriverManager.getConnection()建立与数据库的TCP连接,连接池正是对此步骤的性能优化方案CONNECTIONPOOL03创建语句PreparedStatement支持参数化查询,具有预编译缓存和防注入双重优势PREPAREDSTATEMENT04执行操作executeQuery()返回ResultSet用于查询,executeUpdate()返回影响行数用于增删改QUERY/UPDATE05处理结果ResultSet.next()逐行读取,通过getXXX()获取字段值,注意类型匹配RESULTSET06释放资源必须在finally块或try-with-resources中关闭ResultSet、Statement、Connection,先开后关FINALLYBATCHPROCESSINGJDBC批处理机制(BatchProcessing)批处理通过addBatch()收集SQL语句、executeBatch()批量发送,将多次数据库交互合并为一次,在大批量数据插入场景下性能提升可达10-50倍。MySQL需在连接URL中添加rewriteBatchedStatements=true参数才能真正启用批量优化。01核心API:PreparedStatement.addBatch()将参数化SQL加入批处理队列,executeBatch()统一发送并返回int[]各语句影响行数02性能优势:1000条INSERT单条执行耗时约8-12秒(含网络往返),批处理模式可压缩至0.3-0.8秒,减少95%以上的网络交互03MySQL特殊配置:必须在JDBCURL中添加rewriteBatchedStatements=true,否则驱动仍会逐条发送,无法实现真正批量优化04内存控制:当批量数据超过1万条时,建议按每1000条执行一次executeBatch()并clearBatch(),防止JVM内存溢出05事务配合:批处理应包裹在事务中,执行前setAutoCommit(false),全部成功后commit,任一批次失败则整体rollbackPerformanceBenchmark批处理性能对比:单条执行vs批量执行实测数据表明,随着数据量增长,批处理相对单条执行的性能优势呈指数级扩大。1000条记录时性能比约20倍,10000条时达到100倍以上,批处理是大数据量操作的必选方案。MySQL8.0环境下的INSERT性能测试数据量单条执行耗时批处理耗时性能提升倍数备注100条0.85秒0.08秒10.6x差异尚不明显1,000条8.2秒0.4秒20.5x批处理优势显现5,000条42秒1.2秒35x差距显著扩大10,000条108秒0.9秒120x必须使用批处理50,000条>10分钟4.5秒>130x分批提交防OOM批处理在万级数据量时性能提升超过100倍,是生产环境大数据量操作的必备手段Chapter09·TransactionsJDBC事务管理机制JDBC默认每条SQL自动提交,事务管理需手动关闭自动提交,通过commit/rollback控制事务边界。ACID是理论基础。事务ACID特性原子性事务内所有操作要么全部成功,要么全部回滚,不允许部分完成一致性事务执行前后数据库从一个一致状态转换到另一个一致状态隔离性并发事务互不干扰,通过隔离级别控制脏读、不可重复读、幻读持久性事务一旦提交,其结果永久保存,即使系统崩溃也不会丢失JDBC事务APIsetAutoCommit(false)关闭自动提交,开启手动事务控制,此后所有SQL在commit前不生效commit()提交事务,将本次事务内所有SQL操作永久写入数据库,通常在全部操作成功后调用rollback()回滚事务,撤销本次事务内所有已执行的SQL操作,通常在catch异常块中调用TRANSACTIONISOLATION事务隔离级别详解JDBC定义了四种隔离级别,从低到高分别为READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE。级别越高越能防止并发问题,但锁竞争越激烈、性能越低。MySQL默认REPEATABLE_READ,Oracle默认READ_COMMITTED。四种隔离级别与并发问题对照隔离级别脏读不可重复读幻读性能READ_UNCOMMITTED✗允许✗允许✗允许最高READ_COMMITTED✓防止✗允许✗允许较高REPEATABLE_READ✓防止✓防止✗允许中等SERIALIZABLE✓防止✓防止✓防止最低隔离级别从低到高逐步防止脏读、不可重复读和幻读,但性能依次降低TransactionManagement事务保存点(Savepoint)Savepoint允许在事务内部设置中间检查点,实现部分回滚而非全量回滚。适用于长事务中多步骤操作的场景,某一子步骤失败时仅回滚到最近的保存点,保留之前已完成的操作,提高事务的灵活性和效率。创建保存点setSavepoint("step1")setSavepoint("step1")在当前事务内创建命名保存点,后续可通过该名称进行部分回滚Create回滚到保存点rollback(sp)rollback(sp)将事务回滚到指定保存点,之后操作被撤销,之前操作仍保留Rollback释放保存点releaseSavepoint(sp)releaseSavepoint(sp)释放不再需要的保存点,建议及时释放以节约数据库资源Release典型场景订单处理:验证客户→检查库存→计算价格→生成订单,库存不足时仅回滚到库存检查点Scenario注意事项commit()保存点仅在事务未提交前有效,commit()后自动失效;部分数据库对数量有上限NoticeJDBCAPIReferenceJDBC元数据(MetaData)APIJDBC提供DatabaseMetaData和ResultSetMetaData两类元数据接口,前者描述数据库整体属性,后者描述查询结果集结构。元数据是构建通用DAO、ORM框架和数据库管理工具的基础能力。01conn.getMetaData()通过conn.getMetaData()获取,可查询数据库产品名称、版本号、驱动名称、JDBC版本等全局信息02getTables()getColumns()getTables()方法可枚举数据库中所有表,getColumns()获取指定表的全部列定义,支撑动态表结构探测03supportsTransactions()supportsBatchUpdates()supportsTransactions()、supportsBatchUpdates()等方法用于检测数据库能力,实现跨数据库兼容代码ResultSetMetaData01rs.getMetaData()getColumnCount()通过rs.getMetaData()获取,getColumnCount()返回结果集列数,是动态遍历未知结构结果集的关键入口02getColumnName(i)getColumnLabel(i)getColumnTypeName(i)getColumnName(i)和getColumnLabel(i)分别获取列名和别名,getColumnTypeName(i)获取SQL类型名称03在ORM框架中用于自动映射:根据列名匹配Java对象属性,根据列类型选择对应的getter方法CHAPTER02数据库连接池连接复用原理、主流实现方案与生产环境配置策略Chapter9·Database连接池的核心原理数据库连接是昂贵资源,TCP握手+认证+会话初始化耗时50-200ms。连接池通过"预创建-借用-归还"模式实现连接复用,将连接获取时间从百毫秒级降至微秒级,同时通过最大连接数限制防止资源耗尽,是生产环境数据库访问的基础设施。服务器机房·数据库物理环境01传统模式痛点50-200ms每次操作新建Connection耗时50-200ms(TCP握手+身份认证+会话分配),高并发下连接数不可控导致数据库OOM02连接池模型Borrow/Return启动时预创建N个连接放入池中,应用通过borrowObject()借出、returnObject()归还,连接在池中循环复用03核心参数initialSize初始连接数、maxActive最大活跃连接、maxIdle最大空闲连接、maxWait借出超时时间04生命周期管理Heartbeat空闲连接定期心跳检测、超时连接自动回收、连接泄漏检测(removeAbandoned)防止连接不归还的问题PerformanceBenchmark连接池性能实测对比在100并发、1000次请求下,连接池总耗时仅为传统方式的15%-25%,吞吐量提升3-5倍。单次数据库操作耗时分解(ms)100并发·1000次请求测试场景连接池通过预热和复用机制消除连接创建开销,使数据库操作效率获得数量级提升。连接创建耗时骤降:传统DriverManager每次新建连接需85ms,连接池复用后降至0.02ms,降幅达99.97%。0.02msSQL执行耗时恒定:三种方式下SQL执行均为12ms,连接池不影响查询本身性能,开销优化完全来自连接复用。12ms恒定总效率跃升:单次操作从97ms降至约12ms,HikariCP与Druid表现一致,系统吞吐量提升约4–5倍。4–5×DatabaseConnectionPool主流连接池方案对比HikariCP凭借零拷贝、字节码优化等技术在性能基准测试中领先,已成为SpringBoot默认选择;Druid以完善的监控面板和SQL防火墙在企业级场景中占优;C3P0作为早期方案已逐渐被替代。选型应综合考虑性能需求、运维监控和生态兼容。三大连接池核心特性对比对比维度HikariCPDruidC3P0性能基准最快(基准标杆)接近HikariCP较慢监控能力仅JMX指标内置Web监控面板基础统计SQL防火墙不支持内置WallFilter不支持代码体积130KB极轻量1.4MB中等600KBSpringBoot默认内置需引入starter需手动配置适用场景高性能微服务企业级管理系统遗留系统维护HikariCP性能最优且为SpringBoot默认,Druid监控能力最强适合企业场景Chapter09·ConnectionPoolHikariCP配置与使用实践HikariCP通过HikariConfig配置类完成池参数设定,核心参数包括maximumPoolSize(建议CPU核数×2+1)、connectionTimeout(默认30s)、idleTimeout(默认10min)。作为SpringBoot2.x+默认连接池,仅需在perties中配置spring.datasource前缀属性即可自动注入。核心配置参数01maximumPoolSize=10:池中最大连接数,公式为(CPU核数×2)+有效磁盘数,过大会导致数据库连接竞争加剧02minimumIdle=5:最小空闲连接数,HikariCP建议与maximumPoolSize相同以保持固定连接池大小03connectionTimeout=30000:借出连接最大等待时间(毫秒),超时抛出SQLTransientConnectionException04idleTimeout=600000:连接允许空闲的最长时间(毫秒),仅在minimumIdle小于maximumPoolSize时生效使用方式01Maven依赖:引入com.zaxxer:HikariCP包,Java11+使用5.x版本,Java8使用4.x版本02手动配置:newHikariConfig()设置jdbcUrl/username/password/driverClassName,再newHikariDataSource(config)03SpringBoot集成:application.yml中配置spring.datasource.hikari.*前缀属性,框架自动创建并注入DataSourceBeanPRODUCTION连接池生产环境最佳实践生产环境连接池配置需遵循"够用就好"原则:10-20个连接通常足以支撑数百并发请求。连接泄漏检测、合理的超时配置和监控告警是三大运维保障。01连接数黄金公式:PostgreSQL官方建议connections=(CPU核数×2)+有效磁盘数,10-20个连接通常足够支撑高并发场景。10-2002连接泄漏检测:HikariCP设置leakDetectionThreshold=60000(60秒),连接借出超时未归还即触发告警日志,快速定位泄漏源。60s03代码规范铁律:所有Connection/Statement/ResultSet必须在try-with-resources或finally块中关闭,从源头杜绝连接泄漏。TRY-WITH04监控三指标:activeCount活跃连接数、idleCount空闲连接数、pendingThreads等待线程数,异常波动时及时触发告警。305常见故障排查:获取连接超时→检查连接数是否过小或存在泄漏;数据库CPU飙升→检查连接数是否过大或存在慢SQL。TIMEOUTCHAPTER03DAO设计模式数据访问对象模式的架构分层、接口抽象与工程实践Chapter9·DAOPatternDAO模式概述与分层架构DAO模式将数据访问逻辑封装为独立对象,实现业务层与持久层的解耦。典型三层架构为:表现层(Controller)→业务层(Service)→持久层(DAO),每层通过接口交互。这种分层使代码职责清晰、可独立测试、便于团队协作,是Java企业级开发的基础架构模式。为什么需要DAO01解耦:业务逻辑与SQL语句分离,数据库从MySQL迁移到PostgreSQL时仅需修改DAO层实现02复用:StudentDao的findById()可被成绩管理、宿舍管理等多个业务模块调用,避免SQL重复编写03可测试:DAO层可通过Mock对象进行单元测试,无需启动完整应用或连接真实数据库三层架构模型01表现层(Controller):接收HTTP请求、参数校验、调用Service层、返回响应,不包含任何SQL代码02业务层(Service):实现业务逻辑、事务控制、调用多个DAO完成复杂操作,是核心业务规则的载体03持久层(DAO):封装JDBC操作,提供增删查改方法,对上层屏蔽SQL细节和数据库连接管理CHAPTER09·DAOPATTERNDAO模式四大核心组件完整的DAO实现包含实体类、DAO接口、DAO实现类和数据库工具类四个组件,面向接口编程使上层仅依赖接口而非具体实现,便于替换和测试。实体类Entity与数据库表一一对应的JavaBean,如Student类包含id、name、age、grade属性,提供getter/setter和toString方法JavaBeanDAO接口Interface定义数据操作契约,如IStudentDao声明add、deleteById、findById、findAll等方法签名Contract实现类Impl实现DAO接口,内部使用PreparedStatement执行SQL、ResultSet映射为实体对象、处理SQLExceptionJDBC工具类DBUtil封装DataSource初始化、getConnection获取连接、close释放资源的通用方法,避免重复编写DataSourceDAOFrameworkBaseDao通用基类设计BaseDao通过模板方法模式封装JDBC的通用流程(获取连接→创建语句→设置参数→执行→映射结果→释放资源),子类仅需传入SQL和参数即可完成数据库操作。结合泛型和RowMapper回调接口,可实现类型安全的结果集映射,将DAO实现代码量减少60%以上。通用查询方法query(sql,mapper,params)执行查询并通过RowMapper将每行ResultSet映射为T类型对象RowMapper函数式接口定义mapRow方法,调用方通过Lambda表达式实现自定义映射逻辑内部流程:getConnection→PreparedStatement→循环setObject设置参数→executeQuery→遍历ResultSetquery·RowMapper·Lambda通用更新方法update(sql,params)执行INSERT/UPDATE/DELETE,返回int影响行数,0表示未匹配任何记录batchUpdate(sql,paramsList)批量执行,内部使用addBatch+executeBatch实现批量优化所有方法均在finally块中释放Connection/Statement/ResultSet资源,确保无泄漏update·batchUpdate·finallyDAOPattern·CRUD实战:StudentDao完整实现以学生成绩管理系统为例,StudentDaoImpl继承BaseDao实现IStudentDao接口,利用泛型query()方法和Lambda表达式RowMapper,每个CRUD方法仅需3-5行核心代码。01findById调用query("SELECT*FROMstudentWHEREid=?",rowMapper,id)返回单个Student对象或nullquery·单条02findAll调用query("SELECT*FROMstudentORDERBYid",rowMapper)返回List,支持后续分页扩展List<Student>03add调用update("INSERTINTOstudent(name,age,grade)VALUES(?,?,?)",name,age,grade)INSERT04update调用update("UPDATEstudentSETname=?,age=?,grade=?WHEREid=?",…s.getId())UPDATE05deleteById调用update("DELETEFROMstudentWHEREid=?",id),返回1成功、0记录不存在DELETEFACTORYPATTERN·DIPDAO工厂模式与接口隔离DaoFactory结合配置文件和反射机制创建DAO实例,业务层仅依赖接口而非具体类,持久层实现可无缝替换,业务代码零修改。工厂模式实现01DaoFactory读取perties配置文件中的类名,如studentDao=com.pku.dao.impl.StudentDaoImpl02通过Class.forName()反射加载并实例化DAO对象,缓存到Map中实现单例,避免重复创建03业务层调用DaoFactory.getStudentDao()获取接口引用,运行时可注入JDBC或MyBatis实现接口隔离原则01IStudentDao接口仅声明业务方法,不暴露JDBC相关API(如Connection、PreparedStatement等)02上层Service依赖接口而非实现,符合依赖倒置原则(DIP),编译时不依赖任何JDBC类03支持Mock测试:用Mockito模拟IStudentDao返回预设数据,无需连接真实数据库CHAPTER04安全实践与综合案例SQL注入防护、敏感数据保护与局域网聊天工具数据库设计Security·SQLInjectionSQL注入攻击原理与防护SQL注入通过拼接恶意输入改变SQL语义,PreparedStatement通过参数化查询将输入作为纯数据处理而非SQL代码,从根本上阻断注入。此外还应配合输入校验、最小权限原则和WAF防火墙构建多层防御。攻击原理01'OR1=1--登录绕过:输入'OR1=1--使WHERE条件恒为真,无需密码即可登录管理员账户02UNIONSELECT数据窃取:通过UNIONSELECT拼接额外查询,将密码、信用卡号等敏感数据合并到结果中03;DROPTABLE破坏性攻击:利用;DROPTABLE追加删表语句,造成不可逆数据丢失根源:Statement直接拼接字符串防护方案01?参数化查询:使用?占位符绑定参数,驱动自动转义特殊字符,输入被当作纯数据02parseInt输入白名单校验:数值型强制parseInt转换,字符串限制长度和字符集,拒绝非法输入03DROP/ALTER最小权限原则:数据库账户仅授予必要权限,禁止DROP/ALTER等DDL操作建议配合WAF防火墙多层防御SecurityPractice敏感数据安全管理实践数据库连接信息和用户敏感数据的安全管理是生产环境的底线要求,密码必须加密存储且严禁硬编码。配置文件安全perties中密码使用Jasypt加密(ENC格式),运行时解密,避免明文随代码泄露ENC(xxx)环境变量注入生产环境通过System.getenv读取密码,配置文件仅含占位符,密钥不入版本库ENVINJECT密码存储规范使用BCrypt算法加盐哈希存储用户密码,不可逆,即使拖库也无法还原明文BCRYPT传输加密JDBC连接添加useSSL与requireSSL参数,确保应用与数据库通信经TLS加密SSL/TLS日志脱敏对手机号、身份证号等敏感字段进行掩码处理,防止日志系统成为泄露源MASKChapter9·AdvancedPreparedStatement高级用法与常见陷阱PreparedStatement在LIKE查询和IN子句场景下需要特殊处理:LIKE需将通配符%拼接到参数值中而非SQL模板;IN子句因参数个数不固定,需动态生成对应数量的?占位符。01LIKE模糊查询正确写法:SQL写WHEREnameLIKE?,Java代码传入"%"+keyword+"%",通配符在参数值中拼接错误写法:SQL写WHEREnameLIKE'%?%',?被当作字面字符而非占位符,查询永远无结果特殊字符转义:用户输入的%和_需转义为\%和\_,否则可能被利用进行数据探测02IN子句动态参数核心问题:IN(?,?,?)的参数个数必须与占位符数量一致,运行时才能确定查询几个ID解决方案:根据List.size()动态生成SQL,如IDs=[1,2,3]生成IN(?,?,?),再循环setInt设置每个参数工具封装:BaseDao中提供queryByIn(Stringsql,List<Integer>ids)方法自动处理占位符生成和参数绑定DATABASEDESIGN综合案例:局域网聊天工具数据库设计局域网聊天工具涉及用户、好友关系、消息记录、群组四张核心表,通过外键关联和索引优化支撑消息查询性能。核心表结构设计表名核心字段关键索引设计说明usersid,username,password_hash,nickname,status,created_atUNIQUE(username)密码BCrypt哈希存储friendsid,user_id,friend_id,remark,created_atINDEX(user_id,friend_id)双向好友需插两条记录messagesid,sender_id,receiver_id,content,msg_type,send_time,is_readINDEX(receiver_id,is_read)未读消息高频查询字段建索引groupsid,group_name,owner_id,max_members,created_atINDEX(owner_id)群主ID外键关联users表四张核心表通过外键关联,关键查询字段建立索引保证消息检索性能JAVA·DAO实现消息发送DAO实现(事务+批处理)消息发送需在同一事务中完成三步操作:插入消息记录、更新发送者已发送计数、群消息时为每个成员批量插入消息副本。事务保证原子性——任一步骤失败则整体回滚;群消息使用批处理减少数据库交互次数。01开启事务:conn.setAutoCommit(false),确保后续三步操作在同一事务内,任何异常都触发rollbacksetAutoCommit02插入消息:PreparedStatement执行INSERTINTOmessages(sender_id,receiver_id,content,send_time)VALUES(?,?,?,?)INSERT03群消息批处理:若为群聊,遍历群成员列表,addBatch()批量插入每个成员的消息副本,executeBatch()统一提交addBatch04事务提交:全部操作成功后mit(),catch块中conn.rollback()回滚,finally中归还连接至连接池commit性能优化:100人群消息通过批处理仅需1次数据库交互,相比逐条INSERT减少99%的网络往返开销99%Chapter9·ExceptionHandlingJDBC常见异常与处理策略异常分为驱动、连接、语法、数据、约束与资源六类,需分类施策:连接类可重试,语法类需修复代码。六大常见JDBC异常及处理方案异常类型常见原因处理策略ClassNotFoundExceptionJDBC驱动jar未引入或类名拼写错误检查Maven依赖和驱动类名,MySQL8.0用com.mysql.cj.jdbc.DriverCommunicationsException数据库宕机、网络中断、防火墙阻断端口重试机制(3次指数退避)+告警通知运维检查网络和数据库状态SQLSyntaxErrorExceptionSQL语句拼写错误、表名/列名不存在打印完整SQL排查语法,检查表结构是否匹配,属于代码缺陷需修复DataTruncation插入数据超过列定义长度,如VARCHAR(10)插入20字符前端+后端双重校验输入长度,数据库列长度设计预留余量SQLIntegrityConstraintViolation违反唯一约束或外键约束INSERT前检查唯一键是否已存在,删除前检查外键依赖或级联处理SQLTransientConnectionException连接池耗尽,无法获取可用连接检查连接池配置是否合理、是否存在连接泄漏、并发量是否超出预期六类异常涵盖驱动、连接、语法、数据、约束和资源问题,需分类施策MODERNJDBCJDBC4.0+现代特性JDBC4.0引入SPI自动驱动加载,4.1支持try-with-resources,4.2新增java.time映射,大幅减少样板代码并降低资源泄漏风险。自动驱动加载(4.0+)SPI机制:驱动jar中META-INF/services/java.sql.Driver文件声明驱动类名,DriverManager自动扫描并注册代码简化:移除Class.forName(),仅需确保Maven依赖中有mysql-connector-java即可多驱动共存:classpath中同时有多个驱动时,DriverManager根据URL前缀自动选择匹配驱动try-with-resources(4.1+)语法糖:try块中声明Connection与PreparedStatement,块结束自动关闭所有资源关闭顺序:按声明逆序调用close(),先关PreparedStatement再关Connection,符合先开后关原则异常处理:close()异常被suppressed压制,主异常通过cat

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论