一 22
问题描述:
hibernate技术中对应数据库中每一个表,都会有一个映射文件与之对应,此文件描述数据库表中每一个字段的类型、长度、是否可空等属性。在进行表中记录的插入(更新)操作时,hibernate会根据映射文件中的描述自动生成一个包含所有字段的插入(更新)sql语句,此时如果映射文件中某字段的值为空(NULL)而其在数据库表中定义的默认值不为空,hibernate会将空值插入到表中,而不会使用此字段的默认值。
解决方法:
在hibernate映射文 更多详细内容 »
作者:Jock
一 04
Hibernate 3.2 参考手册中文版
下载文件已经改为chm的版本,压缩后比pdf大概小了100多K,嗯,比较满意。
hibernate_reference下载
Tags:
下载,
参考手册 作者:Jock
十二 26
insert或update时中文出现乱码的解决方法:
在连接串后面加上数据库编码。
<property name="connection.url">
jdbc:mysql://localhost:3306/mysql?useUnicode=true&characterEncoding=utf-8
</property>
作者:Jock
十一 04
package org.jock.hibernate.model;
import java.util.Date;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.criterion.Example;
/**
* Data access object (DAO) for domain model class User.
* @see org.jock.hibernate.model.User
* @author MyEclipse – Hibernate Tools
*/
public class UserDAO extends BaseHibernateDAO {
private static final Log log = LogFactory.getLog(UserDAO.class);
//property constants
public static final String FNAME = “fname”;
public static final String LNAME = “lname”;
public static final String USERNAME = “username”;
public static final String PASSWORD = “password”;
public static final String AUTH = “auth”;
public static final String GRADEID = “gradeid”;
public static final String EMAIL = “email”;
public static final String FLAG = “flag”;
public static final String TEL = “tel”;
public void save(User transientInstance) {
log.debug(“saving User instance”);
try {
getSession().save(transientInstance);
log.debug(“save successful”);
} catch (RuntimeException re) {
log.error(“save failed”, re);
throw re;
}
}
public void delete(User persistentInstance) {
log.debug(“deleting User instance”);
try {
getSession().delete(persistentInstance);
log.debug(“delete successful”);
} catch (RuntimeException re) {
log.error(“delete failed”, re);
throw re;
}
}
public User findById( java.lang.Integer id) {
log.debug(“getting User instance with id: ” + id);
try {
User instance = (User) getSession()
.get(“org.jock.hibernate.model.User”, id);
return instance;
} catch (RuntimeException re) {
log.error(“get failed”, re);
throw re;
}
}
public List findByExample(User instance) {
log.debug(“finding User instance by example”);
try {
List results = getSession()
.createCriteria(“org.jock.hibernate.model.User”)
.add(Example.create(instance))
.list();
log.debug(“find by example successful, result size: ” + results.size());
return results;
} catch (RuntimeException re) {
log.error(“find by example failed”, re);
throw re;
}
}
public List findByProperty(String propertyName, Object value) {
log.debug(“finding User instance with property: ” + propertyName
+ “, value: ” + value);
try {
String queryString = “from User as model where model.”
+ propertyName + “= ?”;
Query queryObject = getSession().createQuery(queryString);
queryObject.setParameter(0, value);
return queryObject.list();
} catch (RuntimeException re) {
log.error(“find by property name failed”, re);
throw re;
}
}
public List findByFname(Object fname) {
return findByProperty(FNAME, fname);
}
public List findByLname(Object lname) {
return findByProperty(LNAME, lname);
}
public List findByUsername(Object username) {
return findByProperty(USERNAME, username);
}
public List findByPassword(Object password) {
return findByProperty(PASSWORD, password);
}
public List findByAuth(Object auth) {
return findByProperty(AUTH, auth);
}
public List findByGradeid(Object gradeid) {
return findByProperty(GRADEID, gradeid);
}
public List findByEmail(Object email) {
return findByProperty(EMAIL, email);
}
public List findByFlag(Object flag) {
return findByProperty(FLAG, flag);
}
public List findByTel(Object tel) {
return findByProperty(TEL, tel);
}
public User merge(User detachedInstance) {
log.debug(“merging User instance”);
try {
User result = (User) getSession()
.merge(detachedInstance);
log.debug(“merge successful”);
return result;
} catch (RuntimeException re) {
log.error(“merge failed”, re);
throw re;
}
}
public void attachDirty(User instance) {
log.debug(“attaching dirty User instance”);
try {
getSession().saveOrUpdate(instance);
log.debug(“attach successful”);
} catch (RuntimeException re) {
log.error(“attach failed”, re);
throw re;
}
}
public void attachClean(User instance) {
log.debug(“attaching clean User instance”);
try {
getSession().lock(instance, LockMode.NONE);
log.debug(“attach successful”);
} catch (RuntimeException re) {
log.error(“attach failed”, re);
throw re;
}
}
}
作者:Jock
十一 02
设计细颗粒度的持久类并且使用<component>来实现映射。
使用一个Address持久类来封装 street, suburb, state, postcode. 这将有利于代码重用和简化代码重构(refactoring)的工作。
对持久类声明标识符属性( identifier properties)。
Hibernate中标识符属性是可选的,不过有很多原因来说明你应该使用标识符属性。我们建议标识符应该是“人造”的(自动生成,不涉及业务含义)。
使用自然键(natural keys)标识
对所有的实体都标识出自然键,用<natural-id>进行映射。实现equals()和hashCode(),在其中用组成自然键的属性进行比较。
为每个持久类写一个映射文件
不要把所有的持久类映射都写到一个大文件中。把 com.eg.Foo 映射到com/eg/Foo.hbm.xml中, 在团队开发环境中,这一点显得特别有意义。
把映射文件作为资源加载
把映射文件和他们的映射类放在一起进行部署。
考虑把查询字符串放在程序外面
如果你的查询中调用了非ANSI标准的SQL函数,那么这条实践经验对你适用。把查询字符串放在映射文件中可以让程序具有更好的可移植性。
使用绑定变量
就像在JDBC编程中一样,应该总是用占位符"?"来替换非常量值,不要在查询中用字符串值来构造非常量值!更好的办法是在查询中使用命名参数。
不要自己来管理JDBC connections
Hibernate允许应用程序自己来管理JDBC connections,但是应该作为最后没有办法的办法。如果你不能使用Hibernate内建的connections providers,那么考虑实现自己来实现org.hibernate.connection.ConnectionProvider
考虑使用用户自定义类型(custom type)
假设你有一个Java类型,来自某些类库,需要被持久化,但是该类没有提供映射操作需要的存取方法。那么你应该考虑实现org.hibernate.UserType接口。这种办法使程序代码写起来更加自如,不再需要考虑类与Hibernate type之间的相互转换。
更多详细内容 »
Tags:
参考手册 作者:Jock
十一 02
本章展示了一些较为复杂的关系映射。
23.1. Employer(雇主)/Employee(雇员)
下面关于Employer 和 Employee的关系模型使用了一个真实的实体类 (Employment)来表述,这是因为对于相同的雇员和雇主可能会有多个雇佣时间段。 对于金额和雇员姓名,用Components建模。
映射文件可能是这样:
<hibernate-mapping>
<class name="Employer" table="employers">
<id name="id">
<generator class="sequence">
<param name="sequence">employer_id_seq</param>
</generator>
</id>
<property name="name"/>
</class>
<class name="Employment" table="employment_periods">
<id name="id">
<generator class="sequence">
<param name="sequence">employment_id_seq</param>
</generator>
</id>
<property name="startDate" column="start_date"/>
<property name="endDate" column="end_date"/>
<component name="hourlyRate" class="MonetaryAmount">
<property name="amount">
<column name="hourly_rate" sql-type="NUMERIC(12, 2)"/>
</property>
<property name="currency" length="12"/>
</component>
<many-to-one name="employer" column="employer_id" not-null="true"/>
<many-to-one name="employee" column="employee_id" not-null="true"/>
</class>
<class name="Employee" table="employees">
<id name="id">
<generator class="sequence">
<param name="sequence">employee_id_seq</param>
</generator>
</id>
<property name="taxfileNumber"/>
<component name="name" class="Name">
<property name="firstName"/>
<property name="initial"/>
<property name="lastName"/>
</component>
</class>
</hibernate-mapping>
用SchemaExport生成表结构。 更多详细内容 »
Tags:
参考手册 作者:Jock
十一 02
22.1. 持久化类
下面的持久化类表示一个weblog和在其中张贴的一个贴子。他们是标准的父/子关系模型,但是我们会用一个有序包(ordered bag)而非集合(set)。
[codes=java]
package eg;
import java.util.List;
public class Blog {
private Long _id;
private String _name;
private List _items;
public Long getId() {
return _id;
}
public List getItems() {
return _items;
}
public String getName() {
return _name;
}
public void setId(Long long1) {
_id = long1;
}
public void setItems(List list) {
_items = list;
}
public void setName(String string) {
_name = string;
}
}
package eg;
import java.text.DateFormat;
import java.util.Calendar;
public class BlogItem {
private Long _id;
private Calendar _datetime;
private String _text;
private String _title;
private Blog _blog;
public Blog getBlog() {
return _blog;
}
public Calendar getDatetime() {
return _datetime;
}
public Long getId() {
return _id;
}
public String getText() {
return _text;
}
public String getTitle() {
return _title;
}
public void setBlog(Blog blog) {
_blog = blog;
}
public void setDatetime(Calendar calendar) {
_datetime = calendar;
}
public void setId(Long long1) {
_id = long1;
}
public void setText(String string) {
_text = string;
}
public void setTitle(String string) {
_title = string;
}
}
[/codes]
22.2. Hibernate 映射 更多详细内容 »
Tags:
参考手册 作者:Jock
十一 02
刚刚接触Hibernate的人大多是从父子关系(parent / child type relationship)的建模入手的。父子关系的建模有两种方法。由于种种原因,最方便的方法是把Parent和Child都建模成实体类,并创建一个从Parent指向Child的<one-to-many>关联,对新手来说尤其如此。还有一种方法,就是将Child声明为一个<composite-element>(组合元素)。 事实上在Hibernate中one to many关联的默认语义远没有composite element贴近parent / child关系的通常语义。下面我们会阐述如何使用带有级联的双向一对多关联(bidirectional one to many association with cascades)去建立有效、优美的parent / child关系。这一点也不难!
21.1. 关于collections需要注意的一点
Hibernate collections被当作其所属实体而不是其包含实体的一个逻辑部分。这非常重要!它主要体现为以下几点:
当删除或增加collection中对象的时候,collection所属者的版本值会递增。
如果一个从collection中移除的对象是一个值类型(value type)的实例,比如composite element,那么这个对象的持久化状态将会终止,其在数据库中对应的记录会被删除。同样的,向collection增加一个value type的实例将会使之立即被持久化。
另一方面,如果从一对多或多对多关联的collection中移除一个实体,在缺省情况下这个对象并不会被删除。这个行为是完全合乎逻辑的--改变一个实体的内部状态不应该使与它关联的实体消失掉!同样的,向collection增加一个实体不会使之被持久化。
实际上,向Collection增加一个实体的缺省动作只是在两个实体之间创建一个连接而已,同样移除的时候也只是删除连接。这种处理对于所有的情况都是合适的。对于父子关系则是完全不适合的,在这种关系下,子对象的生存绑定于父对象的生存周期。
21.2. 双向的一对多关系(Bidirectional one-to-many)
假设我们要实现一个简单的从Parent到Child的<one-to-many>关联。
<set name="children">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
如果我们运行下面的代码
Parent p = …..;
Child c = new Child();
p.getChildren().add(c);
session.save(c);
session.flush();
Hibernate会产生两条SQL语句:
一条INSERT语句,为c创建一条记录
一条UPDATE语句,创建从p到c的连接
这样做不仅效率低,而且违反了列parent_id非空的限制。我们可以通过在集合类映射上指定not-null="true"来解决违反非空约束的问题:
<set name="children">
<key column="parent_id" not-null="true"/>
<one-to-many class="Child"/>
</set>
然而,这并非是推荐的解决方法。 更多详细内容 »
Tags:
参考手册 作者:Jock
十一 02
可以通过一系列Eclipse插件、命令行工具和Ant任务来进行与Hibernate关联的转换。
除了Ant任务外,当前的Hibernate Tools也包含了Eclipse IDE的插件,用于与现存数据库的逆向工程。
Mapping Editor: Hibernate XML映射文件的编辑器,支持自动完成和语法高亮。它也支持对类名和属性/字段名的语义自动完成,比通常的XML编辑器方便得多。
Console: Console是Eclipse的一个新视图。除了对你的console配置的树状概览,你还可以获得对你持久化类及其关联的交互式视图。Console允许你对数据库执行HQL查询,并直接在Eclipse中浏览结果。
Development Wizards: 在Hibernate Eclipse tools中还提供了几个向导;你可以用向导快速生成Hibernate 配置文件(cfg.xml),你甚至还可以同现存的数据库schema中反向工程出POJO源代码与Hibernate 映射文件。反向工程支持可定制的模版。
Ant Tasks:
要得到更多信息,请查阅 Hibernate Tools 包及其文档。
同时,Hibernate主发行包还附带了一个集成的工具(它甚至可以在Hibernate“内部”快速运行)SchemaExport ,也就是 hbm2ddl。
20.1. Schema自动生成(Automatic schema generation)
可以从你的映射文件使用一个Hibernate工具生成DDL。 生成的schema包含有对实体和集合类表的完整性引用约束(主键和外键)。涉及到的标示符生成器所需的表和sequence也会同时生成。
在使用这个工具的时候,你必须 通过hibernate.dialet属性指定一个SQL方言(Dialet),因为DDL是与供应商高度相关的。
首先,要定制你的映射文件,来改善生成的schema。
20.1.1. 对schema定制化(Customizing the schema)
很多Hibernate映射元素定义了可选的length、precision 或者 scale属性。你可以通过这个属性设置字段的长度、精度、小数点位数。
<property name="zip" length="5"/>
<property name="balance" precision="12" scale="2"/>
有些tag还接受not-null属性(用来在表字段上生成NOT NULL约束)和unique属性(用来在表字段上生成UNIQUE约束)。 更多详细内容 »
Tags:
参考手册 作者:Jock
十一 02
19.1. 抓取策略(Fetching strategies)
抓取策略(fetching strategy) 是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL 或条件查询(Criteria Query)中重载声明。
Hibernate3 定义了如下几种抓取策略:
连接抓取(Join fetching) – Hibernate通过 在SELECT语句使用OUTER JOIN(外连接)来 获得对象的关联实例或者关联集合。
查询抓取(Select fetching) – 另外发送一条 SELECT 语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止 延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
子查询抓取(Subselect fetching) – 另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
批量抓取(Batch fetching) – 对查询抓取的优化方案, 通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。 更多详细内容 »
Tags:
参考手册 作者:Jock
近期评论