复习hiernate
Configuration
Configuration 类负责管理 Hibernate 的配置信息
包括如下内容:1,Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)。2,持久化类与数据表的映射关系(*.hbm.xml 文件)。
创建 Configuration 的两种方式
属性文件(hibernate.properties)
Configuration cfg = new
Configuration();
Xml文件(hibernate.cfg.xml)
加载默认名称的配置文件(hibernate.cfg.xml)
Configuration cfg = new
Configuration().configure();
或加载指定名称的配置文件:
Configuration cfg = new
Configuration().configure(“myhibernate.cfg.xml”);
SessionFactory
Configuration对象根据当前的配置信息生成 SessionFactory 对象。SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息(SessionFactory 对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存)。 相关代码如下:
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
SessionFactory是线程安全的。
SessionFactory是生成Session的工厂:
Session session =
sessionFactory.openSession();
构造 SessionFactory 很消耗资源,一般情况下一个应用中只初始化一个 SessionFactory 对象。
Session(一次与数据库的会话)
Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短。Session 中有一个缓存,显式执行flush()方法之前,所有的持久层操作的数据都缓存在 session 对象处。(相当于 JDBC 中的 Connection)
持久化类与 Session 关联起来后就具有了持久化的能力。
Session是线程不安全的
Session 类的一些方法:
取得持久化对象的方法: get() load()
持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()
开启事务: beginTransaction().
管理 Session 的方法:isOpen(),flush(),
clear(), evict(), close()等
Transaction
代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
Transaction tx = session.beginTransaction();
常用方法:
commit():提交相关联的session实例
rollback():撤销事务操作
wasCommitted():检查事务是否提交
Query和Criteria接口
都是查询接口,Query实例包装了HQL查询语句,hql是面向对象的,他引用类名及类的属性名,而不是表名和字段名。Criteria接口完全封装了基于字符串形式的查询语句,比Query接口更面向对象,他擅长执行动态查询。
Hibernate的运行过程
Hibernate的运行过程如下:
1、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息,
2、并用这些信息生成一个SessionFactory对象,
3、然后从SessionFactory对象生成一个Session对象,
4、并用Session对象生成Transaction对象;
A、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、等操作;
B、在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作到数据库中。
动创建表:(hibernate.cfg.xml中配置)
<property name="hbm2ddl.auto">update</property>
create:先删除,再创建
update:如果表不存在就创建,不一样就更新,一样就什么都不做。在开发 的时候使用较多。
create-drop:初始化时创建表,SessionFactory执行close()时删除 表。
validate:验证表结构是否一致,如果不一致,就抛异常。部署时可以使用
对持久化对象的要求
提供一个无参的构造器。使Hibernate可以使用Constructor.newInstance()
来实例化持久 化类。
提供一个标识属性(identifier property)。通常映射为数据库表的主键字段。如果没有该 属性,一些功能将不起作用,如:Session.saveOrUpdate()。
为类的持久化类的字段声明访问方法(get/set)。Hibernate对JavaBeans风格的属性实行 持久化。
使用非final类。在运行时生成代理是Hibernate的一个重要的功能。如果持久化类没有 实现任何接口,Hibnernate 使用
CGLIB 生成代理。如果使用的是 final 类,则无法生 成CGLIB代理。
重写eqauls()和hashCode()方法。如果需要把持久化类的实例放到Set中(当需要进行 关联映射时),则应该重写这两个方法。
OID
为了在系统中能够找到所需对象,需要为每一个对象分配一个唯一的标识号。在关系数据库中称之为主键,而在对象术语中,则叫做对象标识(Object identifier-OID)。
使用基本数据类型和包装类型的区别
基本数据类型和包装类型对应的hibernate映射类型相同(映射是一样的),例:
propertye (默认值):
表明hibernate通过getXXX和setXXX来访问类属性。推荐使用。提高域模型透明性。
field
hibernate通过java反射机制直接访问类属性。对于没有get与set方法的属性可设置该访问策略。
noop
它映射Java持久化类中不存在的属性,即主要用于HQL(用query接口测试,使用hql语句)中,当数据库中有某列,而实体中不存在的情况。
OID,唯一性的标志
关系数据库用主键区分是否是同一条记录。
Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系。对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID赋值。
主键必备条件:
1,不能为null。
2,唯一,不能重复。
3,永远不会改变。
自然主键和代理主键
自然主键:把具有业务含义的字段作为主键叫做自然主键。
代理主键:不具备业务含义的字段,该字段一般取名为“id”。(推荐)
关系数据库按主键区分不同记录
把主键定义为自动增长类型
在my SQL中,把字段设为auto_increment类型,数据库会自动为主键赋值。
在ms SQL server中,把字段设为identity类型,数据库会自动为主键赋值。
oracle从序列(sequence)中获取自动增长的描述符
create sequence seq_customer
increment by 2 start with 1
insert into customers values(seq_customer.curval,’..’)
java与Hibernate如何区分对象
Java语言按内存地址(==)或equals()方法区分不同的对象
Hibernate中用对象表示符(OID)来区分对象
OID是关系数据库中的主键在java对象模型中的等价物。在运行时,hibernate根据OID来维持java对象和数据库记录的对应关系。
Hibernate使用OID来区分对象,不是equals()方法!所以不重写持久化类的hashCode()与equals()方法Hibernate也可以正确运行(但要放到HashSet等集合中时要注意需要重写这两个方法)。
iD和 generator元素配置说明
配置示例:
<id name=“id” type=“long” column=“ID”> <generator class=“increment” /> </id>
<id>元素说明:
设定持久化类的 OID 和表的主键的映射,可以有以下属性:
name: 标识持久化类 OID 的属性名
column: 设置标识属性所映射的数据列的列名(主键字段的名字).
unsaved-value:若设定了该属性, Hibernate 会通过比较持久化类的 OID 值和该属性值来区分当前持久化类的对象是否为临时对象,在Hibernate3中几乎不再需要.
type:指定 Hibernate 映射类型. Hibernate 映射类型是 Java 类型与 SQL 类型的桥梁. 如果没有为某个属性显式设定映射类型, Hibernate 会运用反射机制先识别出持久化类的特定属性的 Java 类型, 然后自动使用与之对应的默认的 Hibernate 映射类型
Java 的基本数据类型和包装类型对应相同的 Hibernate 映射类型. 基本数据类型无法表达 null, 所以对于持久化类的 OID 推荐使用包装类型
<generator>元素说明
设定持久化类设定标识符生成器,可以有一个class属性:
class: 指定使用的标识符生成器全限定类名或其缩写名。
<generator>元素的class属性可以指定的值说明(主键生成策略)
主键生成器 |
描述 |
increment |
适用于代理主键。由hibernate自动以递增的方式生成表识符,每次增量为1。 |
identity |
适用于代理主键。由底层数据库生成表识符。条件是数据库支持自动增长数据类型。 |
sequence |
适用于代理主键。Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列。 |
hilo |
适用于代理主键。Hibernate根据hign/low算法生成标识符。Hibernate把特定表的字段作为“hign”值。默认情况下,采用hibernate_unique_key表的next_hi字段。 |
native |
适用于代理主键。根据底层数据库对自动生成表示符的能力来选择identity、sequence、hilo |
uuid.hex |
适用于代理主键。Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。 |
assigned |
适用于自然主键。由java程序负责生成标识符。不能把setID()方法声明为private的。尽量避免使用自然主键。 |
increment
increment 标识符生成器由 Hibernate 以递增的方式为代理主键赋值
Hibernate 会先读取表中的主键的最大值,向表中插入记录时, 就在 max(id) 的基础上递增,增量为1。
适用范围:
由于 increment生存标识符机制不依赖于底层数据库系统,因此它适合所有的数据库系统。
适用于只有单个 Hibernate 应用进程访问同一个数据库的场合,在多线程情况下会有问题(线程不安全)。
OID必须为long、int或 short 类型,如果把OID定义为byte类型,在运行时会抛出异常
identity
identity 标识符生成器由底层数据库来负责生成标识符, 它要求底层数据库把主键定义为自动增长字段类型。
适用范围:
由于 identity 生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库系统必须支持自动增长字段类型。支持自动增长字段类型的数据库包括:DB2、 Mysql、MSSQLServer、Sybase等。
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常。
sequence
sequence 标识符生成器利用底层数据库提供的序列来生成标识符.
Hibernate 在持久化一个 News 对象时, 先从底层数据库的 news_seq 序列中获得一个唯一的标识号, 再把它作为主键值
适用范围:
由于 sequence 生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列。支持序列的数据库包括:DB2 Oracle 等。
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常。
hilo
(在hilo中这些关键字都不能修改)
hilo 标识符生成器由 Hibernate 按照一种 high/low 算法*生成标识符, 它从数据库的特定表的字段中获取 high 值.
Hibernate 在持久化一个 News 对象时, 由 Hibernate 负责生成主键值. hilo 标识符生成器在生成标识符时, 需要读取并修改 HI_TABLE 表中的 NEXT_VALUE 值.
适用范围:
由于 hilo 生存标识符机制不依赖于底层数据库系统, 因此它适合所有的数据库系统
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常
native (在开发中用得最多)
native 标识符生成器依据底层数据库对自动生成标识符的支持能力, 来选择使用 identity, sequence 或 hilo 标识符生成器.
适用范围:
由于 native 能根据底层数据库系统的类型, 自动选择合适的标识符生成器, 因此很适合于跨数据库平台开发
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常
Hibernate映射类型
内置映射类型
Hibernate |
java |
sql |
取值范围 |
integer int |
int Integer |
INTEGER |
4 |
long |
long Long |
BIGINT |
8 |
short |
short Short |
SMALLINT |
2 |
byte |
byte Byte |
TINYINT |
1 |
float |
float Float |
FLOAT |
4 |
double |
double Double |
DOUBLE |
8 |
big_decimal |
java.math.BigDecinimal |
NUMERIC |
8位含2位小数部分 |
character |
char Character String |
CHAR(1) |
定长字符 |
string |
String |
VARCHAR |
变长串 |
boolean |
boolean Boolean |
BIT |
布尔 |
yes_no |
boolean Boolean |
CHAR(1) |
布尔 |
true_false |
boolean Boolean |
CHAR(1) |
布尔 |
java时间和日期类性
Hibernate |
java |
sql |
取值范围 |
date |
util.Date sql.Date |
DATE |
YYYY-MM-DD |
time |
util.Date sql.Time |
TIME |
HH:MM:SS |
timestamp |
util.Date sql.timestamp |
TIMESTAMP |
YYYYMMDDHHMMSS |
calendar |
java.util.Calendar |
TIMESTAMP |
YYYYMMDDHHMMSS |
calendar_date |
java.util.Calendar |
DATE |
YYYY-MM-DD |
大对象类型的映射
Hibernate |
java |
sql |
binary |
byte[] |
VARBINARY(BLOB) |
text |
String |
CLOB |
serializable |
实现类 |
BARBINARY(BLOB) |
clob |
sql.Clob |
CLOB |
blob |
sql.Blob |
BLOB |
不允许以上类型来定义OID
(Hibernate Reference3.2.2中有)JDBC 类 java.sql.Clob 和 java.sql.Blob的映射。某些程序可能不适合使用这个类型,因为blob 和 clob 对象可能在一个事务之外是无法重用的。(而且, 驱动程序对这种类型的支持充满着补丁和前后矛盾。)
JDK自带的个别java类的映射类型
Hibernate |
java |
sql |
class |
java.lang.Class |
VARCHAR |
locale |
java.util.Locale |
VARCHAR |
timezone |
java.util.TimeZone |
VARCHAR |
currency |
java.util.Currency |
VARCHAR |
集合属性大致有两种:
单纯的集合属性,如像List、Set或数组等集合属性
Map结构的集合属性,每个属性值都有对应的Key映射
集合映射的元素大致有如下几种:
list: 用于映射List集合属性
set: 用于映射Set集合属性
map: 用于映射Map集合性
array: 用于映射数组集合属性
bag: 用于映射无序集合
idbag: 用于映射无序集合,但为集合增加逻辑次序
使用集合属性时,一定要使用接口,而不能声明为具体的实现类。
因为经过Session操作后,集合就变成了Hibernate自己的集合实现类
Set
但Set是无序,不可重复的集合。
<class name="Teacher" table="t_teacher"> <id name="id" column="id" type="int"> <generator class="native"/> </id> <property name="name" column="name" type="string" length="20"></property> <set name="course" table="t_teacher_course" order-by="caurse DESC"> <key column="teacherId"></key> <element type="string" column="caurse" ></element> </set> </class>
order-by 影响是查询顺序(使用较多)
Sort可以影响插入顺序,但是必须是有序集合例如treeset list
测试程序
public class TeacherDao { private static SessionFactory sf; static{ Configuration cfg = new Configuration(); cfg.configure(); cfg.addClass(Teacher.class); sf = cfg.buildSessionFactory(); } @Test public void save() throws Exception{ Set<String> set = new HashSet<String>(); set.add("java软件开发"); set.add("C语言"); set.add("MySql数据库"); Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(set); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } } @Test public void getById() throws Exception{ Teacher teacher = null; Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); teacher = (Teacher) session.get(Teacher.class, 1); System.out.println(teacher.getId()); System.out.println(teacher.getName()); System.out.println(teacher.getCourse().toString()); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } } }
注:映射 Set 集合属性时,如果 element 元素包括 not-null = “true” 属性,则集合属性表以关联持久化类的外键和元素列作为联合主键,否则该表没有主键。但 List 集合属性不会,List 集合属性总是以外键列和元素此序列作为联合主键。
在实际应用中,我遇到要求没有顺序不重复的情况很多,所以一般set集合。
List是有序集合,可以重复
因此持久化到数据库时必须增加一列来表示集合元素的次序。
集合属性只能以接口声明(当持久化某个实例时, Hibernate 会自动把程序中的集合实现类替换成 Hibernate 自己的集合实现类),因此下面代码中,schools的类型能是List,不能是ArrayList,
映射说明
list元素要求用list-index的子元素来映射有序集合的次序列。
集合的属性的值会存放有另外的表中,须以外键关联,用 Key 元素来映射外键列。
当集合元素是基本数据类型及其包装类, 字符串或日期类型时使用 element 来映射集合属性
<list name="course" table="t_teacher_course"> <key column="teacherId"></key> <list-index column="indx"></list-index>不使用index关键字 <element type="string" column="caurse" length="100"></element> </list>
测试程序:
@Test public void save() throws Exception{ List<String> list = new ArrayList<String>(); list.add("java软件开发"); list.add("C语言"); list.add("MySql数据库"); Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(list); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } }
生成的表及插入的数据
数组
数组属性的映射和 List 的处理方式基本一致
数组使用 <array> 元素完成完成映射
<array name="course" table="t_teacher_course"> <key column="teacherId"></key> <list-index column="indx"></list-index> <element type="string" column="course" length="100"></element> </array>
代码:
@Test public void save() throws Exception{ String[] array = new String[]{"java软件开发1","C语言","MySql数据库"}; Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(array); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } }
Bag的特性是:允许重复的元素,但无序。在Java的标准API中并没有提供Bag容器,Hibernate提供自己的Bag实现,允许您将List映射为Bag。
bag元素既可以为List集合属性映射,也可以为Collection集合属性映射。
不管是哪种集合属性,使用bag元素都将被映射成无序集合,而集合属性对应的表没有主键。
Bag 元素只需要 key 元素来映射外键列,使用 element 元素来映射集合属性的每个元素。
<bag name="course" table="t_teacher_course"> <key column="teacherId"></key> <element type="string" column="caurse" ></element> </bag>
测试程序:
@Test public void save() throws Exception{ List<String> list = new ArrayList<String>(); list.add("java软件开发"); list.add("C语言"); list.add("MySql数据库"); Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(list); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } }
Map不仅需要映射属性值,还需要映射属性Key。
Hibnernate 将以外键列和Key列作为联合主键。
Map集合属性使用map元素映射,该元素需要key和map-key两个子元素
key子元素用于映射外键列,
map-key子元素则用于映射Map集合的Key。
map-key和element元素都必须确定type属性
<map name="course" table="t_teacher_course"> <key column="teacherId"></key> <map-key type="string" column="kemu" length="100"></map-key> <element type="string" column="course" length="100"></element> </map>
代码实现:
public void save() throws Exception{ Map<String, String> map = new HashMap<String, String>(); map.put("科目1:", "java软件开发1"); map.put("科目2:", "C语言"); Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(map); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } }
哦对了忘记说一个事情 我这里面的初始化方法是比较老的那种新的请参见 不同版本的 api
复习hiernate的更多相关文章
- iOS总结_UI层自我复习总结
UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ...
- vuex复习方案
这次复习vuex,发现官方vuex2.0的文档写得太简略了,有些看不懂了.然后看了看1.0的文档,感觉很不错.那以后需要复习的话,还是先看1.0的文档吧.
- 我的操作系统复习——I/O控制和系统调用
上篇博客介绍了存储器管理的相关知识——我的操作系统复习——存储器管理,本篇讲设备管理中的I/O控制方式和操作系统中的系统调用. 一.I/O控制方式 I/O就是输入输出,I/O设备指的是输入输出设备和存 ...
- 复习(1)【Maven】
终于开始复习旧知识了,有输入必然要有输出.输入和输出之间的内化过程尤为重要,在复习的同时,真正把学到的东西积淀下来,加深理解. Maven项目概念与配置 Maven是一个项目管理和综合工具.Maven ...
- 《CSS权威指南》基础复习+查漏补缺
前几天被朋友问到几个CSS问题,讲道理么,接触CSS是从大一开始的,也算有3年半了,总是觉得自己对css算是熟悉的了.然而还是被几个问题弄的"一脸懵逼"... 然后又是刚入职新公司 ...
- JS复习--更新结束
js复习-01---03 一 JS简介 1,文档对象模型 2,浏览器对象模型 二 在HTML中使用JS 1,在html中使用<script></script>标签 2,引入外部 ...
- jQuery 复习
jQuery 复习 基础知识 1, window.onload $(function(){}); $(document).ready(function(){}); 只执行函数体重的最后一个方法,事 ...
- jQuery5~7章笔记 和 1~3章的复习笔记
JQery-05 对表单和表格的操作及其的应用 JQery-06 jQuery和ajax的应用 JQery-07 jQuery插件的使用和写法 JQery-01-03 复习 之前手写的笔记.实在懒得再 ...
- HTML和CSS的复习总结
HTML(Hypertext Markup Language)超文本标记语言:其核心就是各种标记!<html> HTML页面中的所有内容,都在该标签之内:它主要含<head>和 ...
随机推荐
- 阿里云服务器 Windows连接不成功 提示“你的凭证不工作” 解决方法
HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -> Control ->Terminal Server -> Wds ...
- shell十分钟教程
1.先介绍下shell的工作原理 Shell可以被称作是脚本语言,因为它本身是不需要编译的,而是通过解释器解释之后再编译执行,和传统语言相比多了解释的过程所以效率会略差于传统的直接编译的语言. 但是s ...
- Oracle两张表关联批量更新其中一张表的数据
Oracle两张表关联批量更新其中一张表的数据 方法一(推荐): UPDATE 表2 SET 表2.C = (SELECT B FROM 表1 WHERE 表1.A = 表2.A) WHERE EXI ...
- 快手 Android 工程师面经
看着我把简历投完之后弹出的"完成"字样,我就十分的激动了,我是一名应届毕业生,老老实实的那种,学过的知识我都一步一个脚印的复习的完了,Lintcode上该刷的题,也妥妥的完成了,但 ...
- Tomcat启动中的一些问题
(a)在eclipse中启动tomcat,在控制台加载的配置却是其他项目的,有时候也不是自己工作空间里的? 出现的一个原因是:在我tomcat的webapp目录下,我放了一个其他项目的war包,在to ...
- 笔记evernote
8542-1090-0308-5951 2786-2836-1103-4104 6835-5846-6090-5388 5443-4068-2394-0845
- HTML5 开发APP(打开相册以及图片上传)
我们开发app,常常会遇到让用户上传文件的功能.比如让用户上传头像.我公司的业务要求是让用户上传支付宝收款二维码,来实现用户提现的功能.想要调用相册要靠HTML Plus来实现.先上效果图 基本功能是 ...
- 内核对象kobject和sysfs(3)——kobj分析
内核对象kobject和sysfs(3)--kobj分析 在分析kobj之前,先总结下kobj的功能: 实现结构的动态管理: 实现内核对象到sysfs的映射: 实现自定义属性的管理. 关注一下kobj ...
- 【原创】07. ajax请求,解决sendRedirect 无效
介绍: 后台基于旧代码用的Filter验证,若 Session过期,则跳转登陆页面 前台框架:EasyUI 问题: 最初后台验证不通过: 1 httpServletResponse.sendRedir ...
- PHP执行linux命令mkdir权限问题
在linux系统中,root帐号执行php命令: mkdir('test', 0777); 结果文件的权限依然为: drwxr-xr-x 2 root root Jul 27 19:30 test ...