数据库中一个数组的默认值设置为0。当用hibernate插入数据时,该数组是不被操作的。结果数组不是0,而是空的。后来google了一下,发现.hbm.xml文件中应该添加了一些参数定义(例子中白色部分),如下:
……
……..
Hibernate映射文件中也有很多我们熟悉的,还有很多值得我关注的地方。
在Hibernate映射文件的classtag中使用dynamic-insert和dynamic-update可以优化生成的SQL语句,提高SQL执行效率,最终提升系统性能。
例如,有一个 User 类。
公共类用户{
/**CreatesanewinstanceofUser*/
publicUser(){
}
privatelongid;
隐私;
privateStringfirstname;
privateStringlastname;
privateSetemailAddresses;
//省略getter和setter方法
}
Hibernate 映射文件(User.hbm.xml,省略头部声明)定义为:
我们编写一个测试类来测试 UserTest。
publicclassUserTestextendsTestCase{
publicUserTest(StringtestName){
超级(测试名称);
}
私人会话;
privateSessionFactorysessionFactory;
protectedvoidsetUp()throwsException{
sessionFactory=HibernateUtil.getSessionFactory();
session=sessionFactory.openSession();
session.getTransaction().begin();
}
protectedvoidtearDown()throwsException{
session.getTransaction().commit();
session.close();
}
/**
*TestofgetAgemethod,ofclassmodel.User.
*/
publicvoidtestSaveUser(){
System.out.println(“================testSaveUser=================”);
Useruser=newUser();
user.setAge(29);
session.save(用户);
assertNotNull(“idisassigned!”,user.getId());
}
publicvoidtestUpdateUser(){
System.out.println(“================testUpdateUser=================”);
Useruser=newUser();
user.setAge(29);
session.save(用户);
assertNotNull(“idisassigned!”,user.getId());
User_user=(User)session.get(User.class,user.getId());
_user.setFirstname(“数组”);
session.update(_user);
}
}
运行测试后,此时会生成完整的SQL语句(注意hibernate属性show_sql设置为true)。
================testSaveUser===================
Hibernate:insertintoUsers(age,firstname,lastname)values(?,?,?)
================testUpdateUser===================
Hibernate:insertintoUsers(age,firstname,lastname)values(?,?,?)
休眠:updateUserssetage=?,firstname=?,lastname=?whereID=?
如果我们添加 dynamic-insert=”true”dynamic-update=”true” ,会如下。
再次运行测试类,你会发现生成的SQL所涉及的数组只包含了User类中改变的属性对应的表数组。
================testSaveUser===================
休眠:插入用户(年龄)值(?)
================testUpdateUser===================
休眠:插入用户(年龄)值(?)
休眠:updateUserssetfirstname=?whereID=?
如果表的结构很复杂,数组很多,使用动态插入和动态更新可以稍微提高性能。
以下是其他配置的说明
Hibernate 允许我们控制映射文件中插入和更新语句的内容。比如在映射文件中
1)
元素插入属性:设置为false,插入语句中不包含该数组,表示永远不会插入,默认为true
2)
元素更新属性:设置为false,更新语句中不包含这个数组sql 触发器 在插入前 改变值,表示永远不会改变,默认为true
3)元素可变属性:设置为false就是放所有
元素的update属性设置为false,表示不会更新对象,默认为true
4)
元素动态插入属性:设置为true,表示插入对象时,会生成动态插入语句。如果这个数组的值为空,则不会添加到插入语句中。默认为假
5)
元素的dynamic-update属性,设置为true,表示当对象更新时,会生成一个动态更新语句。如果这个数组的值为空,则不会添加到更新语句中。默认为假
6)元素动态插入属性:设置为true,表示全部
元素的dynamic-insert属性设置为true,默认为false
7)元素动态更新属性:设置为true,表示全部
元素的动态更新属性设置为true,默认为false
Hibernate 生成动态 SQL 语句所消耗的系统资源(如 CPU、显存等)非常少,不会影响系统的性能。如果表包含N个多组,建议使用dynamic-update属性并将insert属性设置为true,这样在插入和更改数据时,语句中只包含要插入或更改的数组。可以节省SQL语句的执行时间,提高程序的运行效率。
hibernate常用注解说明。
@contentejb3 注解的 API 定义在 javax.persistence.* 包中。
注释说明:
@Entity – 将一个类声明为实体 bean(即,持久 POJO 类)
@Id——注解声明了实体bean的标记属性(对应表中的字段)。
@Table——注解声明实体bean映射指定的表(table)、目录(catalog)和schema的名称
@Column – 注释声明属性到列的映射。注解具有以下属性
name 可选,列名(默认为属性名)
unique 可选,是否对该列设置唯一约束(默认值为false)
nullable 可选,是否将列的值设置为可空(默认值为false)
insertable可选sql 触发器 在插入前 改变值,该列是否作为生成插入语句中的列(默认值为true)
updatable可选,该列是否作为生成更新语句中的列(默认值为true)
columnDefinition 是可选的,覆盖此特定列的 sqlddl 片段(这可能会使不同数据库之间的可移植性变得困难)
table是可选的,定义对应的表(默认为主表)
长度可选,列宽(默认255)
precision 可选,列小数精度(decimalprecision)(默认值0)
scale 可选,如果列小数刻度可用,在此处设置(默认值0)
@GeneratedValue – 注解声明了字段的生成策略。注解具有以下属性
strategy 指定生成的策略(由 JPA 定义),它是一个 GenerationType。默认为 GenerationType.AUTO
GenerationType.AUTO 字段是程序控制的
GenerationType.TABLE 使用特定的数据库表来存储字段
GenerationType.IDENTITY字段由数据库手动生成(主要是手动drop类型)
GenerationType.SEQUENCE 根据底层数据库的序列导出到一个字段中,前提是数据库支持序列。 (这个值要和生成器一起使用)
generator 指定用于生成字段的生成器(可以是 orcale 中的序列)。
@SequenceGenerator – 注解声明了一个数据库序列。注解具有以下属性
name表示该表字段的生成策略名称,在@GeneratedValue中设置的“generator”值中引用
sequenceName 表示用于生成策略的数据库序列名称。
initialValue表示字段的初始值,默认为0.
allocationSize 字段值每次减少的大小,例如设置为1,表示每次创建新记录时手动加1,默认为50.@ >
@GenericGenerator – 注释声明了休眠字段生成策略。支持 13 种策略。注解具有以下属性
name 指定生成器名称
strategy 指定具体生成器的类名(指定生成策略)。
parameters 获取策略指定的特定生成器使用的参数。
十三个策略(策略属性的值)如下:
1.native 对 orcale 使用 Sequence 方法,对 MySQL 和 SQLServer 使用标识(情境字段生成机制),
native表示字段的生成会由数据库来完成,不管hibernate(很常用)
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”native”)
2.uuid使用128位uuid算法生成字段,uuid编码为一串32位16的补码。占用大量空间(字符串类型)。
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”uuid”)
3.hilo想在数据库中多建一张表,默认表名是hibernate_unque_key,默认数组是整数类型,名字是next_hi(很少用)
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”hilo”)
4.assigned字段在插入数据时由程序处理(很常见),这是不指定元素时的默认生成策略。相当于 JPA 中的 AUTO。
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”assigned”)
5.identity 使用 SQLServer 和 MySQL 的自增数组。此方法不能放在 Oracle 中。 Oracle 不支持自增数组。需要设置顺序(常用于 MySQL 和 SQLServer)。相当于 JPA 中的 IDENTITY
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”identity”)
6.select使用触发器生成字段(主要用于初始数据库字段生成机制,较少使用)
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”select”)
7.sequence将小心数据库的序列调用成字段,必须设置序列名,否则hibernate很难找到。
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”sequence”,
参数={@Parameter(name=”sequence”,value=”seq_payablemoney”)})
8.seqhilo是通过hilo算法实现的,字段历史存储在Sequence中,适用于支持Sequence的数据库,比如Orcale(很少用)
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”seqhilo”,
参数={@Parameter(name=”max_lo”,value=”5″)})
9.increment 在插入数据时,hibernate会在字段中添加一个自增字段。但是,休眠实例维护一个计数器,因此当多个实例运行时,不能使用此技术。
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”increment”)
10.foreign 使用另一个相关对象的字段。一般和联合使用。
示例:@Id
@GeneratedValue(generator=”idGenerator”)
@GenericGenerator(name=”idGenerator”,strategy=”foreign”,
参数={@Parameter(name=”property”,value=”info”)})
整数;
@OneToOne
员工信息信息;
11.guid采用数据库底层的guid算法机制,对应MySQL的uuid()函数、SQLServer的newid()函数、ORCALE的rawtohex(sys_guid())函数等
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”guid”)
12.uuid.hex 看uudi,建议换成uuid
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”uuid.hex”)
13.sequence-identitysequence策略扩展,使用立即检索策略获取序列值,需要JDBC3.0和JDK4以上(包括1.4)版本
示例:@GeneratedValue(generator=”paymentableGenerator”)
@GenericGenerator(name=”paymentableGenerator”,strategy=”sequence-identity”,
参数={@Parameter(name=”sequence”,value=”seq_payablemoney”)})
@OneToOne 设置一对一关联。 cascade属性有5个值(只有CascadeType.ALL好用?奇怪),分别是CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、CascadeType.REFRESH(级联刷新)、CascadeType。 MERGE(级联更新)、CascadeType.ALL(全部四个)
方法一
主表:?@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
public from table class get from table class(){return from table object}
从表:没有主表类。
注意:这些技术要求主从表的字段值对应。
方法二
主表:?@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name=”主表字段”)//这里指定数据库中的字段数组。
public from table class get from table class(){return from table class}
从表:@OneToOne(mappedBy=”主表类中的从表属性”)//示例主表用户有一个Heart类型heart的从表属性,这里填写heart
public 主表类获取主表类(){返回主表对象}
注意:@JoinColumn 是可选的。默认值为表中的变量名+“_”+表中的字段(注意这里加的是字段,不是字段对应的变量)。
方法三
主表:@OneToOne(cascade=CascadeType.ALL)
@JoinTable(,
joinColumns=@JoinColumn(name=”主表字段”),
inverseJoinColumns=@JoinColumns(name=”Field from table”)
)
从表:@OneToOne(mappedBy=”主表类中的从表属性”)//示例主表用户有一个Heart类型heart的从表属性,这里填写heart
public 主表类获取主表类(){返回主表对象}
@ManyToOne 设置多对一关联
方法一
@ManyToOne(cascade={CasCadeType.PERSIST,CascadeType.MERGE})
@JoinColumn(name=”field”)
public 主表类获取主表类(){返回主表对象}
方法二
@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
@JoinTable(name=”关联表名”,
joinColumns=@JoinColumn(name=”主表字段”),
inverseJoinColumns=@JoinColumns(name=”Field from table”)
)
@OneToMany 设置一对多关联。 cascade 属性指定关联级别,参考@OneToOne 中的描述。 fetch指定是否延迟加载,取值为FetchType.LAZY表示延迟,FetchType.EAGER表示立即加载
方法一使用这些配置,在“one-port”中添加“multi-port”时,“multi-port”的字段不会改变。在“一端”加载时,您不会得到“多端”。如果使用延迟加载,在读取“多终端”列表时会出现异常,当立即加载多终端时,它是一个空集合(集合元素为0)。
“一侧”配置
@OneToMany(mappedBy=””Multiple” 属性”)
publicListget “multiport” list(){return “multiport” list}
“Multiple”配置参考@ManyToOne。
方法二
“一侧”配置
@OneToMany(mappedBy=””Multiple” 属性”)
@MapKey(name=””多终端”作为Key的属性”)
publicMapget “multiport” list() {return “multiport” list}
“Multiple”配置参考@ManyToOne。
方法3 使用这些配置,在“one-side”中添加“multi-terminal”时,可以更改“multi-terminal”的主键。
“一侧”配置
@OneToMany
@JoinColumn(name=””多终端字段”)
publicListget”multiportlist(){return”multiportlist}
《多终端配置参考@ManyToOne.
———