ulimit值(Linux文件句柄数量)的调整

本文链接: http://www.php-oa.com/2008/04/21/ulimit-linux.html

 

在Linux下面部署应用的时候,有时候会遇上Socket/File: Can’t open so many files的问题,比如还有Squid做代理,当文件打开数到900多时速能就非常快的下降,有可能打不开网页.
其实Linux是有文件句柄限制的,而且Linux默认不是很高,一般都是1024,生产服务器用其实很容易就达到这个数量.

查看方法

我们可以用ulimit -a来查看所有限制值

[root@centos5 ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
max nice                        (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 4096
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
max rt priority                 (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4096
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited||<

其中 “open files (-n) 1024
“是Linux操作系统对一个进程打开的文件句柄数量的限制(也包含打开的SOCKET数量,可影响MySQL的并发连接数目).这个值可用ulimit
命令来修改,但ulimit命令修改的数值只对当前登录用户的目前使用环境有效,系统重启或者用户退出后就会失效.

系统总限制是在这里,/proc/sys/fs/file-max.可以通过cat查看目前的值,修改/etc/sysctl.conf 中也可以控制.

另外还有一个,/proc/sys/fs/file-nr,可以看到整个系统目前使用的文件句柄数量

查找文件句柄问题的时候,还有一个很实用的程序lsof.可以很方便看到某个进程开了那些句柄.也可以看到某个文件/目录被什么进程占用了.

修改方法

若要令修改ulimits的数值永久生效,则必须修改配置文档,可以给ulimit修改命令放入/etc/profile里面,这个方法实在是不方便,还
有一个方法是修改/etc/sysctl.conf .我修改了,测试过,但对用户的ulimits -a
是不会改变的。只是/proc/sys/fs/file-max的值变了.(我给命令放到rc.local中失败)

我认为正确的做法,应该是修改/etc/security/limits.conf
里面有很详细的注释,比如

* soft nofile 32768
* hard nofile 65536

也可以直接运行下面这个shell。直接copy到你的终端中运行就好了.
echo -ne “
* soft nofile 65536
* hard nofile 65536
” >>/etc/security/limits.conf

就可以将文件句柄限制统一改成软32768,硬65536.配置文件最前面的是指domain,设置为星号代表全局,另外你也可以针对不同的用户做出不同的限制

注意.这个当中的硬限制是实际的限制,而软限制,是warnning限制,只会做出warning.其实ulimit命令本身就有分软硬设置,加-H就是硬,加-S就是软
默认显示的是软限制,如果运行ulimit命令修改的时候没有加上的话,就是两个参数一起改变.

生效

修改完重新登录就可以见到.(我的系统是Centos5.1.修改了,重新登录后就立刻生效.可以用ulimit -a 查看确认.)

 

如果你使用squid的话,你要在/etc/init.d/squid的文件加入ulimit -HSn 65535.另外,在squid.conf中也要加入max_filedesc 16384

 

也可在catalina.sh文件里设置:

# —————————————————————————–

JAVA_OPTS=’-server -Xms1024m -Xmx2048m -XX:PermSize=64M -XX:MaxPermSize=128m -Duser.timezone=Asia/Shanghai’
#file open ulimit
ulimit -n 65536

连接池基础与dbcp连接池的使用

1.JDBC数据库连接池的必要性

在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤:  

在主程序(如servletbeans)中建立数据库连接。

进行sql操作

断开数据库连接。

这种模式开发,存在的问题:

普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s1s的时间)。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用.若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。

对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。

这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃.

2.数据库连接池(connection pool

为解决传统开发中的数据库连接问题,可以采用数据库连接池技术。

数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

3.数据库连接池技术的优点

(1)资源重用:由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。

(2)更快的系统反应速度:数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间

(3)新的资源分配手段对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置实现某一应用最大可用数据库连接数的限制避免某一应用独占所有的数据库资源.

(4)统一的连接管理,避免数据库连接泄露在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露

4.两种开源的数据库连接池:

   (1)JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现。

(2)DBCP 数据库连接池是 Apache 软件基金组织下的开源连接池实现, 该连接池依赖该组织下的另一个开源系统:Common-pool. 如需使用该连接池实现,应在系统中增加如下两个 jar 文件:Commons-dbcp.jar:连接池的实现 Commons-pool.jar:连接池依赖库

(5)DBCP连接池使用的两种形式

   (1):直接设置参数的形式:

//创建数据源对象

BasicDataSource bds = new BasicDataSource();

//设置连接数据库的驱动

bds.setDriverClassName(“com.mysql.jdbc.Driver”);

//设置连接数据库的url

bds.setUrl(“jdbc:mysql://localhost:3306/test”);

//设置连接数据库的用户名

bds.setUsername(“root”);

//设置连接数据库的密码

bds.setPassword(“root”);

//设置连接池启动时的初始值

bds.setInitialSize(5);

//设置连接池的最大值

bds.setMaxActive(50);

//最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经

//用不到的连接慢慢释放一部分,一直减少到maxIdle为止

bds.setMaxIdle(20);

//最小空闲值.当空闲的连接数少于该值时,连接池就会预申请一些连接,

//以避免洪峰来时再申请而造成的性能开销

bds.setMinIdle(5);

得到连接:Connection conn = dbs.getConnection();

……..

    (2):读取配置文件(properties)的方式。

                   //构建properties对象

                   Properties properties = new Properties();

                   //加载配置文件

        properties.load(inputSream);

                   //BasicDataSourceFactory利用属性文件的信息创建BasicDataSource数据源

dataSource=BasicDataSourceFactory.createDataSource(properties);

//获取连接

Connection conn = dataSource.getConnection();

 

配置文件内容形式如下(注意key严格遵循大小写)

#连接字符串

url=jdbc:mysql://localhost:3306/test

#用户名

username=root

#密码

password=root

#驱动的类路径

driverClassName=com.mysql.jdbc.Driver

#连接池启动时的初始值

initialSize=1

#连接池的最大值

maxActive=50

#最大空闲数

maxIdle=20

#最小空闲数

                   minIdle=5        

mysql密码忘记

分别在Windows下和Linux下重置了MYSQL的root的密码,整理如下:

在windows下:
打开命令行窗口,停止mysql服务:Net stop mysql
到mysql的安装路径启动mysql,在bin目录下使用mysqld-nt.exe启动,
在命令行窗口执行:mysqld-nt –skip-grant-tables
然后另外打开一个命入令行窗口,执行mysql,此时无需输入密码即可进入。
Java代码
>use mysql
>update user set password=password(“新密码”) where user=”root”;
>flush privileges;
>exit
使用任务管理器,找到mysqld-nt的进程,结束进程!
在重新启动mysql-nt服务,就可以用新密码登录了。

在linux下:
如果 MySQL 正在运行,首先杀之: killall -TERM mysqld。
启动 MySQL :bin/safe_mysqld –skip-grant-tables &
就可以不需要密码就进入 MySQL 了。
然后就是
Java代码
>use mysql
>update user set password=password(“new_pass”) where user=”root”;
>flush privileges
;
重新杀 MySQL ,用正常方法启动 MySQL 。

 

   服务器是mysqld或者是mysqld-nt,它可以注册或删除mysqlwindows中的服务。

不同mysql服务器下有不同的数据库。开启不同的mysql服务器,可以连接不同的数据库。

(1)把mysql服务安装到windows系统服务中:

        mysqld –installed mysql

(2)把mysql服务从windows系统服务中删除:

        mysqld –remove mysql

注:其中mysql称为服务名。

(3)直接输入mysqld,则开启了mysql服务。

(4)关闭mysql:

        mysqladmin -u root -ppublic shutdown.

mysqldump导出数据到mssql

mysqldump -u root -ppassword --no-create-db --no-create-info --complete-insert --compatible=mssql 
 --default-character-set=utf8 --skip-opt --compact  --extended-insert=false  
 dbname tablename|sed "s/\\\'/''/g">tablename.sql

 

–no-create-db 不输出建database的脚本

–no-create-info 不输出创建table的脚本

–complete-insert   完整的插入,输出每个字段(如: insert into table(field1,field2,….) values(value1,value2,…))

–compatible=mssql 教本兼容格式,这里是mssql 这样教本里就会把table的名字和字段名用“号引起来,而不是mssql不能识别的`号。

–default-character-set=utf8 默认编码

–compact 输出尽量少的信息

–extended-insert=false  禁用它,可以每行生成一句insert语句。否则只输出一个insert,如:insert into table values(value1,value2,…),(value1,value2,…),…(value1,value2,..)。这种格式sqlserver不识别。

 

 

mysql中用\转义 字符串里的 单引号等字符,而sqlserver的字符串中两个单引号表示一个单引号。没找到mysqldump指定转义字符的选项。有个fields-escaped-by选项,但只有在输出文本格式的时候有用,输出sql语句的时候不能用。

 

所以只好用sed替换一下。

 

sed "s/\\\'/''/g"

 

ibatis新手上路

概念:

iBATIS , 又是一个O/R Mapping的解决方案(例如 hibernate的ORM 也是解决方案之一.)

网上很多人便将其称为ORM , 但是用过的人, 应该都会觉得并不恰当.

与其称之为一个OR Mapping , 倒不如叫它SQL Mapping…

iBATIS 的特点是小巧, 简单. 但是要求需要熟悉SQL , 不像hibernate那样, 可以让你一句sql 都不用写

同时, 我觉得要写挺多的配置文件的. 可能会比较繁琐.

sample

还是拿最简单的 User 类来测试. User.java  

public class User {  

 

    private int id;  

    private String username;  

    private String userpwd;  

    private String userdesc;  

 

        //Sets and Gets…  



public class User {

private int id;

private String username;

private String userpwd;

private String userdesc;

        //Sets and Gets…

接下来… 马上看看… dao里面的一个方法有多简单~~ UserDao.java

 

Java代码 

public static List getAllUsers() throws SQLException {  

                  

               SqlMapClient sqlMap = Utils.getSqlmap();  

       try {  

            List li = sqlMap.queryForList(“getAllUsers”);  

              

       } catch (SQLException e) {  

               e.printStackTrace();  

        }  

        return li;  



public static List getAllUsers() throws SQLException {

               

               SqlMapClient sqlMap = Utils.getSqlmap();

try {

List li = sqlMap.queryForList(“getAllUsers”);

} catch (SQLException e) {

e.printStackTrace();

}

return li;

是的, dao里面的一个方法只需要这么几句话.

看看怎么实现的吧…

首先, 我们需要一个跟 User 类对应的 配置文件 User.xml(名字相同并不是硬性规定, 只是方便管理)

Xml代码 

< xml version=”1.0″ encoding=”UTF-8″  > 

<!DOCTYPE sqlMap PUBLIC “-//ibatis.apache.org//DTD SQL Map 2.0//EN”  

   “http://ibatis.apache.org/dtd/sql-map-2.dtd”> 

 

<sqlMap namespace=”User”> 

 

        <typeAlias alias=”user” type=”pojo.User”/> 

 

   <select id=”getAllUsers” resultClass=”user”> 

       select * from user order by id;   

    </select> 

</sqlMap> 

< xml version=”1.0″ encoding=”UTF-8″  >

<!DOCTYPE sqlMap PUBLIC “-//ibatis.apache.org//DTD SQL Map 2.0//EN”

   “http://ibatis.apache.org/dtd/sql-map-2.dtd”>

<sqlMap namespace=”User”>

        <typeAlias alias=”user” type=”pojo.User”/>

<select id=”getAllUsers” resultClass=”user”>

select * from user order by id;

</select>

</sqlMap>

接下来, 需要一个另一个配置文件, 将User.xml 加入 其中, 同时还要在里面配置数据源—- 即数据库的连接等等…   SqlMapConfig.xml

Xml代码 

< xml version=”1.0″ encoding=”UTF-8″ > 

 

<!DOCTYPE sqlMapConfig PUBLIC “-//ibatis.apache.org//DTD SQL Map Config 2.0//EN”  

    “http://ibatis.apache.org/dtd/sql-map-config-2.dtd”> 

<sqlMapConfig> 

      

   <properties resource=”sqlmap.properties”/> 

         

    <transactionManager type=”JDBC”> 

        <dataSource type=”SIMPLE”>      

           <property name=”JDBC.Driver” value=”${jdbc.driverClassName}” /> 

            <property name=”JDBC.ConnectionURL” value=”${jdbc.url}” /> 

           <property name=”JDBC.Username” value=”${jdbc.username}” /> 

            <property name=”JDBC.Password” value=”${jdbc.password}” /> 

       </dataSource> 

   </transactionManager> 

    <sqlMap resource=”sql/User.xml” /> 

 

</sqlMapConfig> 

< xml version=”1.0″ encoding=”UTF-8″ >

<!DOCTYPE sqlMapConfig PUBLIC “-//ibatis.apache.org//DTD SQL Map Config 2.0//EN”

“http://ibatis.apache.org/dtd/sql-map-config-2.dtd”>

<sqlMapConfig>

<properties resource=”sqlmap.properties”/>

<transactionManager type=”JDBC”>

<dataSource type=”SIMPLE”>   

<property name=”JDBC.Driver” value=”${jdbc.driverClassName}” />

<property name=”JDBC.ConnectionURL” value=”${jdbc.url}” />

<property name=”JDBC.Username” value=”${jdbc.username}” />

<property name=”JDBC.Password” value=”${jdbc.password}” />

</dataSource>

</transactionManager>

<sqlMap resource=”sql/User.xml” />

</sqlMapConfig>

在这里, 我们把数据库的相关参数保存在了另一个文件中, sqlmap.properties

Java代码 

jdbc.driverClassName=com.mysql.jdbc.Driver  

jdbc.url=jdbc:mysql://localhost:3306/myblog  

jdbc.username=root  

jdbc.password=netjava 

jdbc.driverClassName=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/myblog

jdbc.username=root

jdbc.password=ipanel

这样做的好处, 相信大家也明白..  下次我们再写一个项目的时候, 只需要把这个文件copy 过去, 改掉其中的数据库连接就ok啦 ,  也算是资源的充分利用吧..

至此, 所有的配置文件 都已经上场, 当然上面写的都是最简单的测试, 看起来比较没有那么繁琐, 实际应用时候, 可能最麻烦的地方就是在 配置文件的 sqlmap 的编写…

前面 UserDao.java 的方法中, 有这么一句

Java代码 

1.SqlMapClient sqlMap = Utils.getSqlmap(); 

SqlMapClient sqlMap = Utils.getSqlmap();

Utils 类 就是我们抽取其中的初始化的代码, 单独写成一个类, 当然还是方便重用哈.同时采用的是单实例模式, 相当环保.

  Utils.java

Java代码 

1.public class Utils{  

2.      

3.    private static SqlMapClient sqlMapper;   

4.    public static synchronized SqlMapClient getSqlmap()   

5.    {     

6.          if(sqlMapper==null)   

7.          {   

8.              try {   

9.                  Reader reader = Resources.getResourceAsReader(“SqlMapConfig.xml”);   

10.                  sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);   

11.                  reader.close();   

12.                } catch (IOException e) {   

13.                    e.printStackTrace();   

14.                }   

15.          }   

16.            return sqlMapper;   

17.    }   

18.} 

public class Utils{

private static SqlMapClient sqlMapper;

    public static synchronized SqlMapClient getSqlmap()

    {  

          if(sqlMapper==null)

          {

              try {

                  Reader reader = Resources.getResourceAsReader(“SqlMapConfig.xml”);

                  sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);

                  reader.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

          }

            return sqlMapper;

    }

}

好了,  所有的相关文件都已经上场..  当然, 加上 iBATIS的 jar包是前提 , 还是提醒下, 要注意版本问题…

UserDao 是怎样操作数据库的

首先 , Utils 通过SqlMapConfig.xml里面的配置, 连接到数据库, 取得SqlMap , 同时User.xml 将Sql查询映射成java中可以调用的bean, 通过SqlMap 调用这些bean 就是在执行想对应的sql语句…

  • 大小: 23.1 KB

MySQL默认密码修改的方法

来自于: http://soft.ccw.com.cn/programing/database/htm2008/20080721_468620.shtml

 

对于windows平台来说安装完MySQL后,系统就已经默认生成了许可表和账户,你不需要像在Unix平台上那样执行 mysql_install_db脚本来生成帐户和相应权限许可表。但是如果不是用MSI格式来安装MySQL的话,就需要在安装完以后,手动给 root帐户添加新密码,因为默认情况下的root没有开启密码保护功能,如果不重新赋予root帐户密码,那么许多非本机的连接将 无法成功。具体更新密码步骤如下:

c:\>mysql -u root 

mysql>set password for 'root'@'localhost'=password('newpasswd'); 

mysql>set password for 'root'@'%'=password('newpasswd');

 

 

 //本条可选通过以上设置,root的密码将变为newpasswd这样就完成了根用户root密码的设置工作。

mysql命令记录

从网络上收集,记性不大好使在此做个记录,呵呵

启动mysql服务

引用
    MySQL注册为服务:installdir\bin\mysqld-nt -install

    启动MySQL服务:net start mysql

    停止MySQL服务:net stop mysql

    卸载MySQL服务:installdir\bin\mysqld-nt -remove

启动mysql服务1067错误处理   

   

引用
在windows安装目录下打开my.ini文件,编辑内容(如果没有该文件

    ,则新建一个),至少包含basedir,datadir这两个基本的配置。

    [mysqld]

    # 设置为MYSQL的安装目录

    basedir=d:\mysql6.0

    # 设置为MYSQL的数据目录

    datadir=d:\mysql6.0\data

修改密码:SET PASSWORD FOR root@localhost=PASSWORD(“garyzhou”);

切换数据库:use dbname;

显示所有数据库:show databases;

显示表:show tables;

显示表结构:describe [tablename];

校内网技术架构54chen回忆版

校内网CTO黄晶讲述网站架构变迁-54chen回忆版

 

这是一次公司内部的交流会,主题是校内的发展史和构架讲解,主讲人是校内网CTO黄晶,其中关于架构变迁的一段个人觉得是很具有代表性的过程,特在会上作了大概的笔记,现在是凌晨一点不到,正好清醒头脑进行回忆总结。

每个网站的发展都会按照一个大致相同的路线去完成,当然这里说的是每个相对成功的网站。

第一阶段:

这一阶段没有太大的访问量,甚至只有一台服务器就搞定了所有的访问。DB和前端的代码全都在一起,压力不高。忆者注:我觉得在alexa没进五万的时候,只要不是特殊的应用,基本都在此列吧。

第二阶段:

网站初具规模,DB压力大增,单独的一台DB已经满足不了现在的访问量,开始考虑读写分离的Master-slave库,使用三个及以上的服务器。忆者注:这时网站的alexa基本上会在1-3万的位置,每天的ip在5-10w的样子,当然,DB我们都认为是MySql。

第三阶段:

访问量继续增加,增加到了DB的压力在Master的机器上非常的明显了,Master开始出现吃不消的情况,出现写耗尽。主从也已经不能满足要求,需要进一步解决负载问题,此时要引入Mysql Proxy程序,进行中间层代理,实现负载均衡,易于扩展。忆者注:这时网站已经不可限量了,先恭喜下你的网站能用到这段。

第四阶段:

网站继续发展,进而出现了数据量的成倍增长,原来的N台DB都出现了一个问题,数据量巨大,无法完成正常速度的读写。此时,需要对网站按功能进行垂直划分,比如用户注册登录是一部分、UGC又是另一部分。与此同时,对数据本身进行水平划分,也就是Hash散表或者是散库。

第五阶段:

真的没了。再往下玩就灭了。

其实再进一步第五第六阶段,就是无法预想的未来了,也许有什么突飞猛进的科学技术发明也说不好。

今天和yahoo的agentZhang(openResty作者)聊起,他说到第五个阶段其实应该是BigTable,的确很强大,来自google的作品。不过美中不足的是,它并不像我相像中的那样能够顺利过渡到第五阶段。以下论述来自infoQ:
Todd从定义BigTable的适用范围开始论述。由于BigTable引入的各种代价,只有在以下情况下使用BigTable才能带来益处:a)需要伸缩到巨量的用户数,b)更新与读取操作相比比例很小。Todd还着重强调为了“优化读取速度和可伸缩性”,所采取的理论路线与关系数据库中的做法存在根本的分歧,很可能初看起来是违背直觉甚至相当冒险的。

james下JPA

james的这个版本–james-server 3.0-M2,使用了JPA来进行邮件和其他内容的持久化操作。

JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

JPA的总体思想和现有Hibernate、TopLink,JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:

ORM映射元数据

  JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;

JPA 的API

  用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。

查询语言

  这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。

james的 3.0-M2这个版本,使用了OpenJPA

OpenJPA概要:

OpenJPA 是 Apache 组织提供的开源项目,它的前身是BEA公司的Kodo Java Persistence API,于2006年7月捐献给ASF(Apache Software Foundation),并于2007年8月28日发布了OpenJPA 1.0.0版本。OpenJPA 100%实现了 EJB 3.0(JSR220) 中的 JPA 标准,为开发者提供功能强大、使用简单的持久层数据管理框架。OpenJPA 当然实现了对象关系映射(ORM)与对象关系等功能。OpenJPA 除了可以运行在符合EJB 3.0 标准的EJB容器中之外,还可以作为独立的持久层框架,轻松地与其它JavaEE应用框架集成。

1.加载持久化配置文件

<bean class=”org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>

        <property name=”ignoreUnresolvablePlaceholders” value=”true”/>

        <property name = “location” value=”database.properties”/>

</bean>

database.properties的内容很简单,就是简单的键值对:

database.driverClassName=com.mysql.jdbc.Driver

database.url=jdbc:mysql://localhost:3306/james_mail autoReconnect=true

database.username=root

database.password=111111

vendorAdapter.database=MYSQL

openjpa.streaming=false

我配置的是使用了MYSQL数据库进行持久话操作。

james默认的是DERBY,一个文件型的DB。

2。配置datasource

<bean id=”datasource” class=”org.apache.commons.dbcp.BasicDataSource” destroy-method=”close”>

        <property name=”driverClassName” value=”${database.driverClassName}” />

        <property name=”url” value=”${database.url}” />

        <property name=”username” value=”${database.username}” />

        <property name=”password” value=”${database.password}” />

</bean>

这个就不要解释了

3。配置EntityManager对象

<bean id=”entityManagerFactory” class=”org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean”>

        <property name=”dataSource” ref=”datasource”/>

        <property name=”jpaVendorAdapter” ref=”vendorAdapter”/>

</bean>

EntityManager对象的事务管理方式有两 种,分别为JTA和RESOURCE_LOCAL,即Java Transaction API方法和本地的事务管理。

4.配置persistence.xml

persistence.xml 这个文件在classpath下的META-INF文件夹下

james的persistence.xml 内容如下:

<persistence-unit name=”James” transaction-type=”RESOURCE_LOCAL”>

        <class>org.apache.james.mailbox.jpa.mail.model.JPAHeader</class>

        <class>org.apache.james.mailbox.jpa.mail.model.JPAMailbox</class>

  <class>org.apache.james.mailbox.jpa.mail.model.openjpa.AbstractJPAMessage</class>

        <class>org.apache.james.mailbox.jpa.mail.model.openjpa.AbstractJPAMailboxMembership</class>

      <class>org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMailboxMembership</class>

        <class>org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMessage</class>

        <class>org.apache.james.mailbox.jpa.mail.model.JPAProperty</class>

        <class>org.apache.james.mailbox.jpa.user.model.JPASubscription</class>

        <class>org.apache.james.domainlist.jpa.model.JPADomain</class>

        <class>org.apache.james.user.jpa.model.JPAUser</class>

        <class>org.apache.james.vut.jpa.model.JPAVirtualUser</class>

        <properties>

            <property name=”openjpa.jdbc.SynchronizeMappings” value=”buildSchema(ForeignKeys=true)”/>

            <property name=”openjpa.jdbc.MappingDefaults” value=”ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict”/>

            <property name=”openjpa.jdbc.SchemaFactory” value=”native(ForeignKeys=true)”/>

            <property name=”openjpa.jdbc.QuerySQLCache” value=”false”/>

        </properties>

</persistence-unit>

JPA中的事务类 型通过persistence.xml文件中的“transaction-type”元素配置。例如,配置事务为JTA方式的代码如下所示。

5.JPA的注解

1、@Entity(name=”EntityName”)

     必须,name为可选,对应数据库中一的个表

2、@Table(name=””,catalog=””,schema=””)

     可选,通常和@Entity配合使用,只能标注在实体的class定义处,表示实体对应的数据库表的信息

name:可选,表示表的名称.默认地,表名和实体名称一致,只有在不一致的情况下才需要指定表名

catalog:可选,表示Catalog名称,默认为Catalog(“”).

schema:可选,表示Schema名称,默认为Schema(“”).

3、@id

必须

@id定义了映射到数据库表的主键的属性,一个实体只能有一个属性被映射为主键.置于getXxxx()前.

4、@GeneratedValue(strategy=GenerationType,generator=””)

可选

strategy:表示主键生成策略,有AUTO,INDENTITY,SEQUENCE 和 TABLE 4种,分别表示让ORM框架自动选择,

根据数据库的Identity字段生成,根据数据库表的Sequence字段生成,以有根据一个额外的表生成主键,默认为AUTO

generator:表示主键生成器的名称,这个属性通常和ORM框架相关,例如,Hibernate可以指定uuid等主键生成方式.

5、@Basic(fetch=FetchType,optional=true)

可选

@Basic表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的getXxxx()方法,默认即为@Basic

fetch: 表示该属性的读取策略,有EAGER和LAZY两种,分别表示主支抓取和延迟加载,默认为EAGER.

optional:表示该属性是否允许为null,默认为true

6、@Column

可选

@Column描述了数据库表中该字段的详细定义,这对于根据JPA注解生成数据库表结构的工具非常有作用.

name:表示数据库表中该字段的名称,默认情形属性名称一致

nullable:表示该字段是否允许为null,默认为true

unique:表示该字段是否是唯一标识,默认为false

length:表示该字段的大小,仅对String类型的字段有效

insertable:表示在ORM框架执行插入操作时,该字段是否应出现INSETRT语句中,默认为true

updateable:表示在ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true.对于一经创建就不可以更改的字段,该属性非常有用,如对于birthday字段.

columnDefinition: 表示该字段在数据库中的实际类型.通常ORM框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是 DATE,TIME还是TIMESTAMP.此外,String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库的BLOB或 TEXT字段类型,该属性非常有用.

7、@Transient

可选

@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.

如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,否则,ORM框架默认其注解为@Basic

8、@ManyToOne(fetch=FetchType,cascade=CascadeType)

可选

@ManyToOne表示一个多对一的映射,该注解标注的属性通常是数据库表的外键

optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true

fetch:表示抓取策略,默认为FetchType.EAGER

cascade:表示默认的级联操作策略,可以指定为ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干组合,默认为无级联操作

targetEntity:表示该属性关联的实体类型.该属性通常不必指定,ORM框架根据属性类型自动判断targetEntity.

9、@JoinColumn

可选

@JoinColumn和@Column类似,介量描述的不是一个简单字段,而一一个关联字段,例如.描述一个@ManyToOne的字段.

name:该字段的名称.由于@JoinColumn描述的是一个关联字段,如ManyToOne,则默认的名称由其关联的实体决定.

例如,实体Order有一个user属性来关联实体User,则Order的user属性为一个外键,

其默认的名称为实体User的名称+下划线+实体User的主键名称

10、@OneToMany(fetch=FetchType,cascade=CascadeType)

可选

@OneToMany描述一个一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段.

fetch:表示抓取策略,默认为FetchType.LAZY,因为关联的多个对象通常不必从数据库预先读取到内存

cascade:表示级联操作策略,对于OneToMany类型的关联非常重要,通常该实体更新或删除时,其关联的实体也应当被更新或删除

例如:实体User和Order是OneToMany的关系,则实体User被删除时,其关联的实体Order也应该被全部删除

11、@OneToOne(fetch=FetchType,cascade=CascadeType)

可选

@OneToOne描述一个一对一的关联

fetch:表示抓取策略,默认为FetchType.LAZY

cascade:表示级联操作策略

12、@ManyToMany

可选

@ManyToMany 描述一个多对多的关联.多对多关联上是两个一对多关联,但是在ManyToMany描述中,中间表是由ORM框架自动处理

targetEntity:表示多对多关联的另一个实体类的全名,例如:package.Book.class

mappedBy:表示多对多关联的另一个实体类的对应集合属性名称

两个实体间相互关联的属性必须标记为@ManyToMany,并相互指定targetEntity属性,

需要注意的是,有且只有一个实体的@ManyToMany注解需要指定mappedBy属性,指向targetEntity的集合属性名称

利用ORM工具自动生成的表除了User和Book表外,还自动生成了一个User_Book表,用于实现多对多关联

13、@MappedSuperclass

可选

@MappedSuperclass可以将超类的JPA注解传递给子类,使子类能够继承超类的JPA注解

14、@Embedded

可选

@Embedded将几个字段组合成一个类,并作为整个Entity的一个属性.

例如User包括id,name,city,street,zip属性.

我们希望city,street,zip属性映射为Address对象.这样,User对象将具有id,name和address这三个属性.

Address对象必须定义为@Embededable

另:我的小站:

      NB分享http://www.nbshare.com

mysqlfront注册码

aLuo8QAslIZw/xEq9+A4LczWqdUdCq/fSAgwKBpvj3uLonNP5NnixM+qDj3Od1JzPfm5XpDptwF2zNsIq1PSLNmp9OLRHpT/zkeBy4M6aBTTrNA9bnX4hb9RPpT1nIViykZbiYO/dc33UNBt6MTQX+F8xIrmVrIPkCvS6AaQAwOb+LgykeD7iwLDkUCvTXlP5HHHTYwhtg6+VKRTas04Wm8zvzQnxFNjOpF8F0eBo2wNmKtGz/o8V5lbqTq0cisaqzfb55lH54i6NDGb4DhCVg==