??xml version="1.0" encoding="utf-8" standalone="yes"?> 由new命o(h)开辟内存空间的java对象Q?/p>
eg. Person person = new Person("amigo", "?); 如果没有变量对该对象q行引用Q它?yu)被java虚拟机回收?/p>
瞬时对象在内存孤立存在,它是携带信息的蝲体,不和数据库的数据有Q何关联关p,在Hibernate中,可通过session的save()或saveOrUpdate()Ҏ(gu)瞬时对象与数据库相兌Qƈ数据对应的插入数据库中Q此时该瞬时对象转变成持久化对象?/p>
处于该状态的对象在数据库中具有对应的记录Qƈ拥有一个持久化标识。如果是用hibernate的delete()Ҏ(gu)Q对应的持久对象变成瞬时对象,因数据库中的对应数据已被删除Q该对象不再与数据库的记录关联?/p>
当一个session执行close()或clear()、evict()之后Q持久对象变成脱对象,此时持久对象?x)变成脱对象,此时该对象虽然具有数据库识别|但它已不在HIbernate持久层的理之下?/p>
持久对象h如下特点Q?/p>
1. 和session实例兌Q?/p>
2. 在数据库中有与之兌的记录?/p>
当与某持久对象关联的session被关闭后Q该持久对象转变对象。当q对象被重新关联到session上时Qƈ再次转变成持久对象?/p>
q对象拥有数据库的识别|可通过update()、saveOrUpdate(){方法,转变成持久对象?/p>
q对象h如下特点Q?/p>
1. 本质上与瞬时对象相同Q在没有M变量引用它时QJVM?x)在适当的时候将它回Ӟ 2. 比瞬时对象多了一个数据库记录标识倹{?/p>
1Q它是线E安全的Q这意味着它的同一个实例可以被应用的各个线E共享?/p>
2Q它是重量的,q意味着不能随意创徏或销毁它的实例。如果应用只讉K一个数据库Q只需创徏一个SessionFactory实例Q在应用初始化的时候创实例。如果应用同时访问多个数据库Q则需要ؓ(f)每个数据库创Z个单独的SessionFactory实例?/p>
之所以说SessionFactory是重量的,是因为它需要一个很大的~存Q用来存N定义的SQL语句以及(qing)映射元数据等。用戯可以为SessionFactory配置一个缓存插Ӟq个~存插g被称为Hibernate的第二~存Q该~存用来存放被工作单元读q的数据Q将来其它工作单元可能会(x)重用q些数据Q因此这个缓存中的数据能够被所有工作单元共享,一个工作单元通常对应一个数据库事务?/p>
1Q不是线E安全的Q因此在设计软g架构Ӟ应该避免多个U程׃n同一个Session实例Q?/p>
2QSession实例是轻量的,所谓轻量Q是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以l常创徏和销毁Session对象Q例如ؓ(f)每个客户h分配单独的Session实例Q或者ؓ(f)每个工作单元分配单独的Session实例?/p>
Session有一个缓存,被称为Hibernate的第一U缓存,它存放被当前工作单元加蝲的对象。每个Session实例都有自己的缓存,q个Session实例的缓存,q个Session实例的缓存只能被当前工作单元讉K?/p>
Hibernate应用可通过一致的Transaction接口来声明事务边界,q有助于应用在不同环境或容器中移植?/p>
]]>
]]>
table="table_name" (2)
schema="schema_name" (3)
lazy="true|false" (4)
inverse="true|false" (5)
cascade="all|none|save-update|delete|all-delete-orphan" (6)
sort="unsorted|natural|comparatorClass" (7)
order-by="column_name asc|desc" (8)
where="arbitrary sql where condition" (9)
outer-join="true|false|auto" (10)
batch-size="N" (11)
access="field|property|ClassName" (12)
>
<key .... />
<index .... />
<element .... />
</set>
(1) name 集合属性的名称
(2) table Q可选——默认ؓ(f)属性的名称Q这个集合表的名U?不能在一对多的关联关pM使用)
(3) schema (可? 表的schema的名U? 他将覆盖在根元素中定义的schema
(4) lazy (可选——默认ؓ(f)false) lazy(可?-默认为false) 允许延迟加蝲Qlazy initialization Q?不能在数l中使用)
(5) inverse (可选——默认ؓ(f)false) 标记q个集合作ؓ(f)双向兌关系中的方向一端?nbsp;
(6) cascade (可选——默认ؓ(f)none) 让操作联到子实?nbsp;
(7) sort(可?指定集合的排序顺? 其可以ؓ(f)自然?natural)或者给定一个用来比较的cR?nbsp;
(8) order-by (可? 仅用于jdk1.4) 指定表的字段(一个或几个)再加上asc或者desc(可?, 定义Map,Set和Bag的P代顺?nbsp;
(9) where (可? 指定L的SQL where条g, 该条件将在重新蝲入或者删除这个集合时使用(当集合中的数据仅仅是所有可用数据的一个子集时q个条g非常有用)
(10) outer-join(可?指定q个集合,只要可能,应该通过外连?outer join)取得。在每一个SQL语句? 只能有一个集合可以被通过外连接抓?译者注: q里提到的SQL语句是取得集合所属类的数据的Select语句)
(11) batch-size (可? 默认?) 指定通过延迟加蝲取得集合实例的批处理块大("batch size"Q?nbsp;
(12) access(可?默认为属性property):Hibernate取得属性值时使用的策?
]]>
]]>
1. 配置数据?/span>
?/span>Hibernate.cfg.xml中既可以配置JDBCQ也可以配置JNDI。在本小节中讲述数据源如何配|?/span>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 各属性的配置-->
<!?/span>?/span>true表示?/span>Hibernate发送给数据库的sql昄出来 -->
<property name="show_sql">true</property>
<!-- SQL方言Q这边设定的?/span>MySQL -->
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!-- 一ơ读的数据库记录?/span> -->
<property name="jdbc.fetch_size">50</property>
<!-- 讑֮Ҏ(gu)据库q行扚w删除 -->
<property name="jdbc.batch_size">30</property>
<!?/span>下面?/span>JNDI的配|?/span> -->
<!-- 数据源的名称 -->
<property name="connection.datasource">java:comp/env/jdbc/datasourcename</property>
<!-- Hibernate的连接加载类 -->
<property name="connection.provider_class">net.sf.hibernate.connection.DatasourceConnectionProvider</property>
<property name="dialect">net.sf.hibernate.dialect.SQLServerDialect</property>
<!?/span>映射文g -->
<mapping resource="com/amigo/pojo/User.hbm.xml"/>
<mapping resource="com/amigo/pojo/Org.hbm.xml"/>
</session-factory>
</hibernate-configuration>
c3p0q接池是Hibernate推荐使用的连接池Q若需要用该q接池时Q需要将c3p0?/span>jar包加入到classpath中?/span>c3p0q接池的配置CZ如下Q?/span>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 昄实际操作数据库时?/span>SQL -->
<property name="show_sql">true</property>
<!-- SQL方言Q这边设定的?/span>MySQL -->
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!--驱动E序Q在后箋的章节中讲q?/span>mysql?/span>sqlserver?/span>Oracle数据库的配置 -->
<property name="connection.driver_class">……</property>
<!-- JDBC URL -->
<property name="connection.url">……</property>
<!-- 数据库用户名 -->
<property name="connection.username">user</property>
<!-- 数据库密?/span> -->
<property name="connection.password">pass</property>
<property name="c3p0.min_size">5</property>
<property name="c3p0.max_size">20</property>
<property name="c3p0.timeout">1800</property>
<property name="c3p0.max_statements">50</property>
<!-- 对象与数据库表格映像文g -->
<mapping resource="com/amigo/pojo/User.hbm.xml"/>
<mapping resource="com/amigo/pojo/Org.hbm.xml"/>
</session-factory>
</hibernate-configuration>
在上q配|中Q?/span>HibernateҎ(gu)配置文g生成q接Q再交给c3p0理?/span>
proxool?/span>c3p0以及(qing)dbcp不一P它是自己生成q接的,因此q接信息攑֜proxool配置文g中。用它Ӟ需要将proxool-0.8.3.jar加入?/span>classespath中?/span>配置举例如下Q?/span>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 昄实际操作数据库时?/span>SQL -->
<property name="show_sql">true</property>
<!-- SQL方言Q这边设定的?/span>MySQL -->
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!—proxool的配|?/span> -->
<property name="proxool.pool_alias">pool1</property>
<property name="proxool.xml">ProxoolConf.xml</property>
<property name="connection.provider_class">net.sf.hibernate.connection.ProxoolConnectionProvider</property>
<!-- 对象与数据库表格映像文g -->
<mapping resource="com/amigo/pojo/User.hbm.xml"/>
<mapping resource="com/amigo/pojo/Org.hbm.xml"/>
</session-factory>
</hibernate-configuration>
?/span>hibernate.cfg.xml的同目录下编?/span>proxool的配|文Ӟ(x)ProxoolConf.xmlQ该文g的配|实例如下:(x)
ProxoolConf.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- the proxool configuration can be embedded within your own application's.
Anything outside the "proxool" tag is ignored. -->
<something-else-entirely>
<proxool>
<alias>pool1</alias>
<!--proxool只能理p׃生的q接-->
<!-- 驱动?/span>url-->
<!-- jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=GBK-->
<driver-url>… </driver-url>
<!-- 驱动c,eg. com.mysql.jdbc.Driver-->
<driver-class>… </driver-class>
<driver-properties>
<!-- 数据库用户名Q?/span>eg. value?/span>root-->
<property name="user" value="…"/>
<!-- 数据库密码,eg. value?/span>root-->
<property name="password" value="…."/>
</driver-properties>
<!-- proxool自动侦察各个q接状态的旉间隔(毫秒),侦察到空闲的q接马上回?/span>,时的销?/span>-->
<house-keeping-sleep-time>90000</house-keeping-sleep-time>
<!-- 指因未有I闲q接可以分配而在队列中等候的最大请求数,过q个h数的用户q接׃?x)被接?/span>-->
<maximum-new-connections>20</maximum-new-connections>
<!-- 最保持的I闲q接?/span>-->
<prototype-count>5</prototype-count>
<!-- 允许最大连接数,过了这个连接,再有hӞ排在队列中{候,最大的{待h数由maximum-new-connections军_-->
<maximum-connection-count>100</maximum-connection-count>
<!-- 最连接数-->
<minimum-connection-count>10</minimum-connection-count>
</proxool>
</something-else-entirely>
?/span>hibernate3.0中,已经不再支持dbcp了,hibernate的作者在hibernate.org中,明确指出在实践中发现dbcp?/span> BUG,在某些种情会(x)产生很多I接不能释放,所以抛弃了?/span>dbcp的支持。若需要?/span>dbcpQ开发h员还需要将commons-pool-1.2.jar ?/span>commons-dbcp-1.2.1.jar两个jar包加入到classpath中?/span>dbcp?/span>c3p0一P都是?/span>hibernate建立q接的?/span>
?/span>hibernate2.0中的配置建立如下Q?/span>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 昄实际操作数据库时?/span>SQL -->
<property name="show_sql">true</property>
<!-- SQL方言Q这边设定的?/span>MySQL -->
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!--驱动E序Q在后箋的章节中讲q?/span>mysql?/span>sqlserver?/span>Oracle数据库的配置 -->
<property name="connection.driver_class">……</property>
<!-- JDBC URL -->
<property name="connection.url">……</property>
<!-- 数据库用户名,eg. root -->
<property name="connection.username">…</property>
<!-- 数据库密?/span>, eg. root-->
<property name="connection.password">…</property>
<property name="dbcp.maxActive">100</property>
<property name="dbcp.whenExhaustedAction">1</property>
<property name="dbcp.maxWait">60000</property>
<property name="dbcp.maxIdle">10</property>
<property name="dbcp.ps.maxActive">100</property>
<property name="dbcp.ps.whenExhaustedAction">1</property>
<property name="dbcp.ps.maxWait">60000</property>
<property name="dbcp.ps.maxIdle">10</property>
<!-- 对象与数据库表格映像文g -->
<mapping resource="com/amigo/pojo/User.hbm.xml"/>
<mapping resource="com/amigo/pojo/Org.hbm.xml"/>
</session-factory>
</hibernate-configuration>
?/span>hibernate中,可以配置很多U数据库Q例?/span>MySql?/span>Sql Server?/span>OracleQ?/span>MySql的配|D例如下:(x)
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 各属性的配置-->
<!?/span>?/span>true表示?/span>Hibernate发送给数据库的sql昄出来 -->
<property name="show_sql">true</property>
<!-- SQL方言Q这边设定的?/span>MySQL -->
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!-- 一ơ读的数据库记录?/span> -->
<property name="jdbc.fetch_size">50</property>
<!-- 讑֮Ҏ(gu)据库q行扚w删除 -->
<property name="jdbc.batch_size">30</property>
<!--驱动E序-->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- JDBC URL -->
<property name="connection.url">jdbc:mysql://localhost/dbname?characterEncoding=gb2312</property>
<!-- 数据库用户名-->
<property name="connection.username">root</property>
<!-- 数据库密?/span>-->
<property name="connection.password">root</property>
<!?/span>映射文g -->
<mapping resource="com/amigo/pojo/User.hbm.xml"/>
<mapping resource="com/amigo/pojo/Org.hbm.xml"/>
</session-factory>
</hibernate-configuration>
上面使用的驱动类?/span>com.mysql.jdbc.Driver。需要将MySql的连接器jar?/span>(eg. mysql-connector-java-5.0.4-bin.jar)加入?/span>classpath中?/span>
本小节讲qC?/span>Sql Server数据库的hibernateq接讄Q在此只l出q接部分的内容,其余部分?/span>2.2.1.5一P在此不再赘述。内容如下:(x)
<!--驱动E序-->
<property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
<!-- JDBC URL -->
<property name="connection.url">jdbc:jtds:sqlserver://localhost:1433;DatabaseName=dbname</property>
<!-- 数据库用户名-->
<property name="connection.username">sa</property>
<!-- 数据库密?/span>-->
<property name="connection.password"></property>
上例的驱动类使用的是jtds的驱动类Q因此读者需要将jtds?/span>jar?/span>(eg. jtds-1.2.jar)加入?/span>classpath中?/span>
本小节讲qC?/span>Sql Server数据库的hibernateq接讄Q在此只l出q接部分的内容,其余部分?/span>2.2.1.5一P在此不再赘述。内容如下:(x)
<!--驱动E序-->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<!-- JDBC URL -->
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:dbname</property>
<!-- 数据库用户名-->
<property name="connection.username">test</property>
<!-- 数据库密?/span>-->
<property name="connection.password">test</property>
上例使用的驱动类为:(x)oracle.jdbc.driver.OracleDriverQ开发h员需要将相关?/span>jar包(ojdbc14.jarQ加入到classpath中?/span>
http://www.tkk7.com/amigoxie/archive/2007/12/29/171395.html
本节讲述如何使用Hibernate实现记录的增、删、改和查功能?/span>
?/span>Hibernate中用查询时Q一般?/span>Hql查询语句?/span>
HQLQ?/span>Hibernate Query LanguageQ,?/span>Hibernate的查询语a?/span>SQL非常相像。不q?/span>HQL?/span>SQL的最Ҏ(gu)的区别,是它是面向对象的?/span>
使用HQL旉要注意以下几点:(x)
l 大小写敏?/span>
因ؓ(f)HQL是面向对象的Q而对象类的名U和属性都是大写敏感的,所?/span>HQL是大写敏感的?/span>
Eg.
HQL语句Q?/span>from Cat as cat where cat.id > 1;?/span>from Cat as cat where cat.ID > 1;是不一L(fng)Q这点与SQL不同?/span>
l from子句
Eg. from CatQ该句返?/span>Cat对象实例Q开发h员也可以l其加上别名Q?/span>eg. from Cat as catQ对于多表查询的情况Q可参考如下:(x)
from Cat as cat, Dog as dog
其它斚w都与SQLcMQ在此不再赘q?/span>
接下来讲一个在Hibernate中查询的例子?/span>
List list = session.createQuery("from User as user order by user.loginName").list();
List list = session.find("from User as user where user.loginName=?",
loginName,
Hibernate.STRING);
Eg1. 此例采用“?”占位W的方式
String hql = "from User as user where user.loginName=? and user.orgId=? ";
Query query = session.createQuery(hql);
query.setParameter(1, 'amigo');
query.setParameter(2, new Long(1)) ;
List list = query .list();
Eg2. 此例采用“:paramName”的方?/span>
String hql = "from User as user where user.loginName=:loginName and user.orgId=:orgId ";
Query query = session.createQuery(hql);
query.setParameter('loginName', 'amigo');
query.setParameter('orgId', new Long(1)) ;
List list = query .list();
int count = (Integer) session.createQuery("select count(*) from User").uniqueResult().intValue();
q种一般是在记录需要分늚时候需要用刎ͼ例如Q在如下的代码中Q限制查询的开始记录的位置?/span>50Q最大查询条Cؓ(f)50?/span>
String hql = "from User as user order by user.loginName";
int firstResult= 50;
int maxResults = 50;
Query query = session.createQuery(hql);
query = query.setFirstResult(firstResult);
query.setMaxResults(maxResults);
在某些情况下Q也需要用到子查询Q例如在下面的例子中Q?/span>User为用户对象,UserRole为用户与角色兌对象。如?/span>HQL语句没有分配角色的用户对象查找出来?/span>
String hql = "from User user where user.loginName"
+ " not in(select ur.user.loginName from UserRole ur) ";
List list = (session.createQuery(hql)).list();
对于某些复杂的查询语句,需要调用某U特定的数据库的特定函数才能解决Q?/span>Hibernate虽然不推荐用原?/span>SQL语句来查询,因ؓ(f)q将破坏数据库的易移植性,但是Hibernate中也提供了用原?/span>SQLq行查询的方法,只需要获得连接即可?/span>
Eg. 在下面的例子中,用到?/span>Sql Server数据库中的原?/span>sql语句Q如下所C:(x)
String timeUnit = "13";
String sql = "select count(*) count, CONVERT(VARCHAR(" + timeUnit +"), log.gen_datetime,121) timeUnit " + "from Log log";
SQLQuery query = session.createSQLQuery(sql)
.addScalar("count", Hibernate.INTEGER)
.addScalar("timeUnit", Hibernate.STRING);
List list = query.list();
在数据库中新增记录在Hibernate中不需要?/span>insert命o(h)Q只需要构造新增的对象后,调用Session对象?/span>save(…)Ҏ(gu)卛_?/span>
新增单个对象的实例如下,该实例将在用戯中新增一条记录?/span>
Session session = HibernateSessionFactory.getSession();
Transaction ts = null;
try {
ts = session.beginTransaction();
User user = new User();
user.setLoginName("amigo");
user.setFullName("阿蜜?/span>");
……
session.save(user) ;
ts.commit();
} catch (Exception e) {
if (ts != null) {
ts.rollback();
}
} finally {
HibernateSessionFactory.closeSession();
}
对于扚w新增对象的情况,需要在新增一部分对象?/span>flush?/span>clear一ơ,例如Q没扚w新增20个对象时手动?/span>flush一ơ,假设?/span>listZ个用户列表,里面包含很多User对象Q那么要实现这些对象的扚w新增Q可采用如下Ҏ(gu)Q?/span>
Session session = HibernateSessionFactory.getSession();
Transaction ts = null;
try {
ts = session.beginTransaction();
for (int i = 0; i < list.size(); i++) {
User user = (User) list.get(i);
session.save(user) ;
if (i % 20 == 0) {
session.flush();
session.clear();
}
}
ts.commit();
} catch (Exception e) {
if (ts != null) {
ts.rollback();
}
} finally {
HibernateSessionFactory.closeSession();
}
?/span>hibernate中,更新对象前不需要用查询语句:(x)update…Q一般需要在取得需要更新的持久化对象后Q执?/span>Session对象?/span>update(…)Ҏ(gu)。例如:(x)
Session session = HibernateSessionFactory.getSession();
Transaction ts = null;
try {
ts = session.beginTransaction();
//取得持久化对?/span>
User user = session.get(User.class, "amigo");
//寚w要修改的属性进行修?/span>
user.setFullName("阿蜜?/span>");
……
session.update(user) ;
ts.commit();
} catch (Exception e) {
if (ts != null) {
ts.rollback();
}
} finally {
HibernateSessionFactory.closeSession();
}
一般在取得某对象后Q开发h员可以调?/span>Session对象?/span>delete(…)Ҏ(gu)删除该对象?/span>
Eg. 下面的实例中取得loginNameQ主键)?#8220;amigo”?/span>User对象后,它删除?/span>
Session session = HibernateSessionFactory.getSession();
Transaction ts = null;
try {
ts = session.beginTransaction();
//取得持久化对?/span>
User user = session.get(User.class, "amigo");
session.delete(user) ;
ts.commit();
} catch (Exception e) {
if (ts != null) {
ts.rollback();
}
} finally {
HibernateSessionFactory.closeSession();
}
对于扚w删除对象的情况,开发h员可以在取得待删除的对象列表后,一个一个的对象删除,对于每个对象的删除方法,?/span>3.4.1节。开发h员还可以hql语句来做扚w删除?/span>
Eg. 该实例通过delete语句来删除记录,除了loginName?#8220;amigo”的对象ؓ(f)Q其余都删除Q代码如下所C:(x)
Session session = HibernateSessionFactory.getSession();
Transaction ts = null;
try {
ts = session.beginTransaction();
String hql = "delete User as user where user.loginName != 'amigo'";
Query query = session.createQuery(hql);
int count = query.executeUpdate();
ts.commit();
System.out.println("delete count : " + count); //删除条数
} catch (Exception e) {
if (ts != null) {
ts.rollback();
}
} finally {
HibernateSessionFactory.closeSession();
}
http://www.tkk7.com/amigoxie/archive/2008/01/01/171972.html当出?/span>net.sf.hibernate.MappingException: Error reading resource:…异常时一般是因ؓ(f)映射文g出现错误?/span>
当出?/span>net.sf.hibernate.MappingException: Resource: … not found是因?/span>XML配置文g没找到所_(d)有可能是攄目录不正,或者没其加入hibernate.cfg.xml中?/span>
当出?/span>net.sf.hibernate.PropertyNotFoundException: Could not find a setter for property name in class …Ӟ原因一般是因ؓ(f)XML映射文g中的属性与对应?/span>JavacM的属性的getter?/span>setterҎ(gu)不一致?/span>
当出?/span>org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save():异常Ӟ一般是因ؓ(f)<id>元素配置不正,<id>元素~少其子元素<generator></generator>的配|引赗?/span>
解决Ҏ(gu)Q?/span><id>元素映射了相应数据库表的主键字段Q对其子元素<generator class="">,其中class的取值可以ؓ(f)increment?/span>identity?/span>sequence?/span>hilo?/span>native……{,更多的可参?/span>hibernate参考文,一般取其gؓ(f)native 。具体可参?/span>2.2.2.1节?/span>
当出?/span>a different object with the same identifier value was already associated with the sessionӞ一般是因ؓ(f)?/span>hibernate中同一?/span>session里面有了两个相同标识但是是不同实体?/span>
有如下几U解x案:(x)
Q?/span>1Q?/span>session.clean()Q如果在clean操作后面又进行了saveOrUpdate(object){改变数据状态的操作Q有可能?x)报?/span>"Found two representations of same collection"异常?/span>
Q?/span>2Q?/span>session.refresh(object)Q当object不是数据库中已有数据的对象的时候,不能使用session.refresh(object)因ؓ(f)该方法是?/span>hibernate?/span>session中去重新?/span>objectQ如?/span>session中没有这个对象,则会(x)报错所以当你?/span>saveOrUpdate(object)之前q需要判断一下?/span>
Q?/span>3Q?/span>session.merge(object)Q?/span>Hibernate里面自带的方法,推荐使用?/span>
当出?/span>SQL Grammer Exception,Could not execute JDBC batch update异常Ӟ一般是由如下问题引P(x)
Q?/span>1Q?/span>SQL语句中存在语法错误或是传入的数据有误;
Q?/span>2Q数据库的配|不合法Q或者说是配|有误。较Ҏ(gu)出现的有数据表的映射文g(,hbm.xml文g)配置有误Q?/span>Hibernate.cfg.xml文g配置有误;
Q?/span>3Q?/span> 当前的数据库用户权限不Q不能操作数据库。以是以Oracle 数据库ؓ(f)例,q种情况下在错误提示中会(x)昄java.sql.BatchUpdateException: ORA-01031: insufficient privilegesq样的信息?/span>
针对上面的各U原因,开发h员可以找出对应的解决Ҏ(gu)?/span>
http://www.tkk7.com/amigoxie/category/19976.html配置文g的基本结构如下:(x)
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="包名">
<class name="cd" table="表名">
<id name="主键?/span>javacM的字D名" column="对应表中字段" type="cd ">
<generator class="主键生成{略"/>
</id>
……
</class>
</hibernate-mapping>
Hibernate的主键生成策略有如下几种Q?/span>
1) assigned
主键由外部程序负责生成,?/span> save() 之前指定?/span>
2) hilo
通过hi/lo 法实现的主键生成机Ӟ需要额外的数据库表或字D|供高位值来源?/span>
3) seqhilo
?/span>hilo cMQ通过hi/lo 法实现的主键生成机Ӟ需要数据库中的 SequenceQ适用于支?/span> Sequence 的数据库Q如Oracle?/span>
4) increment
主键按数值顺序递增。此方式的实现机制ؓ(f)在当前应用实例中l持一个变量,以保存着当前的最大|之后每次需要生成主键的时候将此值加1作ؓ(f)主键。这U方式可能生的问题是:(x)不能在集下使用?/span>
5) identity
采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL 中的主键生成机制?
6) sequence
采用数据库提供的 sequence 机制生成主键。如 Oralce 中的Sequence?/span>
7) native
?Hibernate Ҏ(gu)使用的数据库自行判断采用 identity、hilo、sequence 其中一U作Z键生成方式?
8) uuid.hex
?Hibernate Z128 ?UUID 法 生成16 q制数|~码后以长度32 的字W串表示Q作Z键?
9) uuid.string
?/span>uuid.hex cMQ只是生成的主键未进行编码(长度16Q,不能应用?/span> PostgreSQL 数据库中?/span>
10) foreign
使用另外一个相兌的对象的标识W作Z键?
主键配置举例如下Q?/span>
<id name="id" column="id" type="java.lang.Integer">
<generator class="native"/>
</id>
另外q可以扩?/span>Hibernate的类来做自己的主键生成策略,具体例子见:(x)http://www.javaeye.com/topic/93391?/span>
开发h员可以打开|址Q?/span>http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd
来查?/span>hibernate3.0?/span>dtd信息Q可看到property的定义如下:(x)
<!ELEMENT property (meta*,(column|formula)*,type?)>
<!ATTLIST property name CDATA #REQUIRED>
<!ATTLIST property node CDATA #IMPLIED>
<!ATTLIST property access CDATA #IMPLIED>
<!ATTLIST property type CDATA #IMPLIED>
<!ATTLIST property column CDATA #IMPLIED>
<!ATTLIST property length CDATA #IMPLIED>
<!ATTLIST property precision CDATA #IMPLIED>
<!ATTLIST property scale CDATA #IMPLIED>
<!ATTLIST property not-null (true|false) #IMPLIED>
<!ATTLIST property unique (true|false) "false">
<!ATTLIST property unique-key CDATA #IMPLIED>
<!ATTLIST property index CDATA #IMPLIED> <!-- include the columns spanned by this property in an index -->
<!ATTLIST property update (true|false) #IMPLIED>
<!ATTLIST property insert (true|false) #IMPLIED>
<!ATTLIST property optimistic-lock (true|false) "true"> <!-- only supported for properties of a class (not component) -->
<!ATTLIST property formula CDATA #IMPLIED>
<!ATTLIST property lazy (true|false) "false">
<!ATTLIST property generated (never|insert|always) "never">
它的各属性中比较常用的有Q?/span>nameQ对应的javacȝ属性名Uͼ?/span>columnQ对应的表中的字D)?/span>tyopeQ属性的cdQ?/span>eg.java.lang.StringQ?/span>not-nullQ设|该属性是否ؓ(f)I,?/span>true时表C非I,默认?/span>falseQ和length(字段的长度限?/span>)?/span>
Eg1. <property name="accessname" column="accessName" type="java.lang.String" not-null="true" />
Eg2. <property name="state" column="state" type="java.lang.Byte" not-null="true" />
Eg3. <property name="description" column="description" type="java.lang.String" />
一对多关系一般是用在一个表与另一个表存在外键兌的时候,例如用户表的l织id与组l表存在外键兌Q则“一”方ؓ(f)l织表,“?#8221;方ؓ(f)用户表,因ؓ(f)一个组l可以包含多个用P而一个用户只能隶属于一个组l?/span>
对于存在一对多关系和多对一关系的双方,需要在…hbm.xml中进行相应配|,q时?#8220;一”方(例如Q组l)需要在映射文g中添?/span><set…></set>元素Q因为它包含多个“?#8221;方的对象Q一般的格式如下Q?/span>
<set name="java映射cM对应的属?/span>" inverse="true" lazy="true">
<key column="表中对应字段"/>
<one-to-many class="多方的类"/>
</set>
Eg.
<set name="userSet" inverse="true" lazy="true">
<key column="orgId"/>
<one-to-many class="User"/>
</set>
“?#8221;方(例如Q用P隶属于一?#8220;一”方对象,一般的格式如下Q?/span>
<many-to-one name="java映射cM对应的属?/span>" column="表中对应字段" class="cd" not-null="true" />
Eg.
<many-to-one name="org" column="orgId" class="Organization" not-null="true" />
一对一关系相对一对多关系来说比较?yu)见Q但也在某些情况下要用到Q例如有一个用L(fng)基本信息表(USERQ和一个用L(fng)密码表(PASSWDQ就存在一对一的关pR下面来看一下一对一关系?/span>Hibernate的配|?/span>
其中主表Q?/span>eg. 用户的基本信息表Q的配置如下Q?/span>
<one-to-one name="主表对象中子表对象的属性名" class="子表对象的类?/span>" cascade="save-update"/>
Eg. <one-to-one name="password" class="com.amigo.dao.pojo.Passwd" cascade="save-update"/>
子表Q?/span>eg. 用户的密码表Q的配置如下Q?/span>
<one-to-one name="子表对象中主表对象的属性名" class="主表对象的类?/span>" constrained="true" />
Eg. <one-to-one name="user" class="com.amigo.dao.pojo.User " constrained="true" />
在数据库设计Ӟ一般将多对多关p{换ؓ(f)两个一对多Q或多对一Q关p,例如在基于角色的权限pȝ中,用户和角色存在的关系是典型的多对多关系Q即一个用户可以具有多个角Ԍ而一个角色又可以为多个用h有,一般在设计Ӟ都会(x)加一个用户与角色的关联表Q该表与用户表以?qing)角色表都存在外键关联?/span>
在本节中讲q的是没有分解的多对多关pdHibernate中如何配|。设|格式如下:(x)
<set name="java对象的属性名" table="表名" cascade="all" outer-join="false">
<key column="表的对应字段"/>
<many-to-many class="另一个表的对象类" column="另一个表的字D?/span>"/>
</set>
Eg. 上述的多对多关系可以表示为:(x)
t_user方:(x)
<set name="roleSet" table="t_user" cascade="all" outer-join="false">
<key column="roleId"/>
<many-to-many class="com.amigo.dao.pojo.Role" column="roleId"/>
</set>
t_role方:(x)
<set name="userSet" table="t_role" cascade="all" outer-join="false">
<key column="roleId"/>
<many-to-many class="com.amigo.dao.pojo.User" column="roleId"/>
</set>
在本节中D一?/span>.hbm.xml映射文g的例子,让开发h员对其有一个感性的认识。接下来讲述一个用戯Q?/span>tbl_userQ、用户与角色兌表(tbl_user_roleQ、角色表Q?/span>tbl_roleQ以?qing)组l表Q?/span>tbl_organizationQ的例子?/span>
Q?/span>1Q?/span>tbl_user
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.amigo.dao.pojo">
<class name="User" table="tbl_user">
<id name="loginname" column="loginName" type="java.lang.String">
<generator class="assigned"/>
</id>
<property name="name" column="name" type="java.lang.String" not-null="true" />
<property name="password" column="password" type="java.lang.String" not-null="true" />
<property name="mobile" column="mobile" type="java.lang.String" />
<property name="telephone" column="telephone" type="java.lang.String" />
<property name="email" column="email" type="java.lang.String" />
<property name="createtime" column="createTime" type="java.util.Date" not-null="true" />
<property name="lastlogintime" column="lastLoginTime" type="java.util.Date" />
<property name="logintimes" column="loginTimes" type="java.lang.Long" not-null="true" />
<property name="state" column="state" type="java.lang.Byte" not-null="true" />
<property name="description" column="description" type="java.lang.String" />
<many-to-one name="organization" column="orgId" class="Organization" not-null="true" />
<set name="userRoleSet" inverse="true" cascade="all-delete-orphan" lazy="true">
<key column="loginName"/>
<one-to-many class="UserRole"/>
</set>
</hibernate-mapping>
Q?/span>2Q?/span>tbl_organization
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.amigo.dao.pojo">
<class name="Organization" table="tbl_organization">
<id name="orgid" column="orgId" type="java.lang.Long">
<generator class="native"/>
</id>
<property name="parentorgid" column="parentOrgId" type="java.lang.Long" not-null="true" />
<property name="orgname" column="orgName" type="java.lang.String" not-null="true" />
<property name="orgfullname" column="orgFullName" type="java.lang.String" />
<property name="orglevel" column="orgLevel" type="java.lang.Integer" not-null="true" />
<property name="state" column="state" type="java.lang.Byte" not-null="true" />
<property name="description" column="description" type="java.lang.String" />
<property name="creator" column="creator" type="java.lang.String" />
<property name="createtime" column="createTime" type="java.util.Date" />
<set name="userSet" inverse="true" lazy="true">
<key column="orgId"/>
<one-to-many class="User"/>
</set>
</class>
</hibernate-mapping>
Q?/span>3Q?/span>tbl_user_role
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.cotel.netvote.dao.model">
<class name="UserRole" table="tbl_user_role">
<id name="urid" column="urId" type="java.lang.Integer">
<generator class="native"/>
</id>
<many-to-one name="role" column="roleId" class="Role" not-null="true" />
<many-to-one name="user" column="loginName" class="User" not-null="true" />
</class>
</hibernate-mapping>
Q?/span>4Q?/span>tbl_ role
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.cotel.netvote.dao.model">
<class name="Role" table="tbl_role">
<id name="roleid" column="roleId" type="java.lang.Integer">
<generator class="native"/>
</id>
<property name="rolename" column="roleName" type="java.lang.String" not-null="true" />
<property name="createdate" column="createDate" type="java.util.Date" not-null="true" />
<property name="description" column="description" type="java.lang.String" />
<set name="userRoleSet" inverse="true" lazy="true" cascade="all">
<key column="roleId"/>
<one-to-many class="UserRole"/>
</set>
</class>
</hibernate-mapping>
http://www.tkk7.com/amigoxie/archive/2007/12/31/171831.html