hibernate之insert和update控制实战
2016年02月03日 17:59:58
阅读数:5458
Hibernate在初始化阶段,会根据对象-关系映射文件生成预编译SQL语句。
1.insert,例如Customer类,初始化时根据映射文件生成预编译SQL
-
insert into CUSTOMERS (NAME, EMAIL, PASSWORD, PHONE, ADDRESS, SEX, IS_MARRIED, DESCRIPTION, IMAGE, BIRTHDAY, REGISTERED_TIME, ID)
-
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2.update,生成的预编译SQL
-
update CUSTOMERS set NAME=?, EMAIL=?, PASSWORD=?, PHONE=?, ADDRESS=?, SEX=?, IS_MARRIED=?, DESCRIPTION=?, IMAGE=?, BIRTHDAY=?,
-
REGISTERED_TIME=? where ID=?
3.delete,生成预编译SQL
delete from CUSTOMERS where ID=?
注意:以上SQL语句中的?号代表的是JDBC中PreparedStatement中的参数。所有这些SQL语句存放在SessionFactory中,当Session调用save(),update(),
delete(),load()方法时,从缓存中根据找到对应的SQL,同时,将具体参数绑定在具体位置,然后执行SQL。
4.控制insert和update分析
根据上面Hibernate默认打印出来的SQL语句可以看出,每一个SQL语句执行时,都包括了数据库表中的所有字段,这种行为,有时候不是我们想要的,
比如,我们想让表中的某个字段永远都更新不到,如果我们自己写SQL,不把这个目标字段更新就行了,但是Hibernate需要采取一定手段,才能达到
我们的目标,SQL从映射文件而来,解决问题还得回到映射文件上去。
要想解决问题,很简单,比如我们不想更新address,可以在映射文件中加一个update属性,设置成false:
<property name="address" update="false" column="ADDRESS" type="string" />
当我们再次执行更新时,从Hibernate打印的SQL能够看出,更新语句中少了刚才设置成不让更新的ADDRESS=?字段,SQL语句变成:
-
update CUSTOMERS set NAME=?, EMAIL=?, PASSWORD=?, PHONE=?, SEX=?, IS_MARRIED=?, DESCRIPTION=?, IMAGE=?, BIRTHDAY=?, REGISTERED_TIME=?
-
where ID=?
注意:控制insert和update映射属性如下:
5.实例演示,实例只做了property的update设置,别的自己根据表格列出的属性,修改后可以很容易测试出其作用
--------实体类
-
package com.lanhuigu.hibernate.entity;
-
import java.io.Serializable;
-
import java.sql.Date;
-
import java.sql.Timestamp;
-
public class Customer implements Serializable{
-
private static final long serialVersionUID = -2934493050228154410L;
-
private Long id;
-
private String name;
-
private String email;
-
private String password;
-
private int phone;
-
private boolean married;
-
private String address;
-
private char sex;
-
private String description;
-
private byte[] image;
-
private Date birthday;
-
private Timestamp registeredTime;
-
public Customer(){}
-
public Long getId() {
-
return id;
-
}
-
public void setId(Long id) {
-
this.id = id;
-
}
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public String getEmail() {
-
return email;
-
}
-
public void setEmail(String email) {
-
this.email = email;
-
}
-
public String getPassword() {
-
return password;
-
}
-
public void setPassword(String password) {
-
this.password = password;
-
}
-
public int getPhone() {
-
return phone;
-
}
-
public void setPhone(int phone) {
-
this.phone = phone;
-
}
-
public boolean isMarried() {
-
return married;
-
}
-
public void setMarried(boolean married) {
-
this.married = married;
-
}
-
public String getAddress() {
-
return address;
-
}
-
public void setAddress(String address) {
-
this.address = address;
-
}
-
public char getSex() {
-
return sex;
-
}
-
public void setSex(char sex) {
-
this.sex = sex;
-
}
-
public String getDescription() {
-
return description;
-
}
-
public void setDescription(String description) {
-
this.description = description;
-
}
-
public byte[] getImage() {
-
return image;
-
}
-
public void setImage(byte[] image) {
-
this.image = image;
-
}
-
public Date getBirthday() {
-
return birthday;
-
}
-
public void setBirthday(Date birthday) {
-
this.birthday = birthday;
-
}
-
public Timestamp getRegisteredTime() {
-
return registeredTime;
-
}
-
public void setRegisteredTime(Timestamp registeredTime) {
-
this.registeredTime = registeredTime;
-
}
-
}
-------映射文件xxx.hbm.xml
-
<?xml version="1.0"?>
-
<!DOCTYPE hibernate-mapping PUBLIC
-
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
-
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
-
<!-- 1.hibernate-mapping对象关系映射的根元素,其它元素必须嵌套在此元素内 -->
-
<hibernate-mapping package="com.lanhuigu.hibernate.entity"><!-- 2.package为实体类在哪个包下 -->
-
<!--
-
3.class中name为持久化的实体类(Customer),table为映射到数据库中的表名(CUSTOMERS),
-
如果没有设置table,默认类名作为表名
-
-->
-
<class name="Customer" table="CUSTOMERS">
-
<!--
-
4.以下配置属性解释:
-
4.1 name为实体类属性
-
4.2 column为映射到数据库中的字段名,如果没有配置column,默认使用name属性作为映射后数据库表字段名
-
4.3 type为字段类型,如果没有设置type,映射时自动采用实体类的java类型,对应映射数据库字段类型
-
java类型映射到数据库类型参照表:
-
java类型>>>>>>>>>>数据库类型
-
string VARCHAR
-
int INT
-
character CHAR
-
boolean BIT
-
text TEXT
-
binary BLOB
-
date DATE
-
timestamp TIMESTAMP
-
4.4 not-null设置该字段是否允许为null,
-
4.5 length设置字段的长度
-
-->
-
<!-- 设置主键 -->
-
<id name="id" column="ID" type="long">
-
<!-- 主键生成方式-->
-
<generator class="increment"/>
-
</id>
-
<!-- 基本属性,基本属性必须设置在主键之口-->
-
<property name="name" column="NAME" type="string" length="25" not-null="true" access="property"/>
-
<property name="email" column="EMAIL" type="string" not-null="true" />
-
<property name="password" column="PASSWORD" type="string" not-null="true" />
-
<property name="phone" column="PHONE" type="int" />
-
<property name="address" update="false" column="ADDRESS" type="string" />
-
<property name="sex" column="SEX" type="character" />
-
<property name="married" column="IS_MARRIED" type="boolean" />
-
<property name="description" column="DESCRIPTION" type="text" />
-
<property name="image" column="IMAGE" type="binary" />
-
<property name="birthday" column="BIRTHDAY" type="date" />
-
<property name="registeredTime" column="REGISTERED_TIME" type="timestamp" />
-
</class>
-
</hibernate-mapping>
-------hibernate.cfg.xml
-
<!DOCTYPE hibernate-configuration PUBLIC
-
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
-
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
-
<!-- hibernate-configuration为hibernate配置头文件 -->
-
<hibernate-configuration>
-
<!-- 配置session-factory,
-
SessionFactory是Hibernate的工厂类,
-
该类负责Hibernate的配置和Hiberante的Session接口中save(),update(),delete(),load(),find()的操作
-
-->
-
<session-factory>
-
<!-- 1.数据库连接配置 -->
-
<!-- 数据库连接url -->
-
<property name="connection.url">jdbc:mysql://192.168.200.12:3306/hbtest</property>
-
<!-- 数据库连接用户名 -->
-
<property name="connection.username">root</property>
-
<!-- 数据库连接口令 -->
-
<property name="connection.password">root123</property>
-
<!-- 数据库连接驱动 -->
-
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
-
<!-- 数据库方言 -->
-
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
-
<!-- 数据库连接池大小配置 -->
-
<property name="connection.pool_size">1</property>
-
<!-- 配置使用二级缓存的类 -->
-
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
-
<!-- 一次读的数据库记录数 -->
-
<property name="jdbc.fetch_size">50</property>
-
<!-- 设定对数据库进行批量删除条数 -->
-
<property name="jdbc.batch_size">30</property>
-
<!-- 2.是否打印sql配置 -->
-
<property name="show_sql">true</property>
-
<!-- 3.对象-映射关系文件的位置 -->
-
<mapping resource="com/lanhuigu/hibernate/entity/Customer.hbm.xml" />
-
</session-factory>
-
</hibernate-configuration>
-----设置前和设置后只需把property中的update去掉或增加,或者设置成true或false,再根据控制台打印的SQL十分清楚地看到明显的差距,效果十分明显。
-
package com.lanhuigu.hibernate.test;
-
import org.hibernate.Session;
-
import org.hibernate.SessionFactory;
-
import org.hibernate.Transaction;
-
import org.hibernate.cfg.Configuration;
-
import org.hibernate.tool.hbm2ddl.SchemaExport;
-
import com.lanhuigu.hibernate.entity.Customer;
-
public class TestHibernate {
-
public static void main(String[] args) {
-
SessionFactory sessionFactory;
-
Configuration configuration = new Configuration().configure();
-
sessionFactory = configuration.buildSessionFactory();
-
//自动建表(create)
-
//SchemaExport export = new SchemaExport(configuration);
-
//export.create(true, true);
-
Session session = sessionFactory.openSession();
-
Transaction tr = session.beginTransaction();
-
//保存(insert)
-
/*Customer customer = new Customer();
-
customer.setId(new Long(1));
-
customer.setName("test");
-
customer.setEmail("123456789@qq.com");
-
customer.setPassword("123456");
-
customer.setAddress("世外桃源");
-
session.save(customer);*/
-
//更新(update)
-
Customer customer = new Customer();
-
customer.setId(new Long(1));
-
customer.setName("test");
-
customer.setEmail("123456789@qq.com");
-
customer.setPassword("222222");
-
customer.setAddress("世外桃源");
-
session.update(customer);
-
//删除(delete)
-
/*Customer customer = new Customer();
-
customer.setId(new Long(1));
-
customer.setName("test");
-
customer.setEmail("123456789@qq.com");
-
customer.setPassword("222222");
-
customer.setAddress("世外桃源");
-
session.delete(customer);*/
-
tr.commit();
-
session.close();
-
}
-
}
结果分析:
通过两种情况得到的SQL,可以清楚地看到SQL中ADDRESS=?有无区别。
注意:
1.测试前,请搭建好自己的hibernate开发环境,导入hibernate必须包和对应数据库驱动包
2.记得建表--插入数据--再做更新,避免报空指针异常或其它异常。(可以根据测试类,根据我代码注释,从建表到更新,一个代码一个代码的放开;)
3.测试更新时,记得修改映射文件xxx.hbm.xml
4.根据表格中列出的映射属性,对应修改,可以看到对应的作用结果。