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=?
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" />
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>
<!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("[email protected]"); customer.setPassword("123456"); customer.setAddress("世外桃源"); session.save(customer);*/ //更新(update) Customer customer = new Customer(); customer.setId(new Long(1)); customer.setName("test"); customer.setEmail("[email protected]"); customer.setPassword("222222"); customer.setAddress("世外桃源"); session.update(customer); //删除(delete) /*Customer customer = new Customer(); customer.setId(new Long(1)); customer.setName("test"); customer.setEmail("[email protected]"); customer.setPassword("222222"); customer.setAddress("世外桃源"); session.delete(customer);*/ tr.commit(); session.close(); } }
通过两种情况得到的SQL,可以清楚地看到SQL中ADDRESS=?有无区别。
注意:
1.测试前,请搭建好自己的hibernate开发环境,导入hibernate必须包和对应数据库驱动包
2.记得建表--插入数据--再做更新,避免报空指针异常或其它异常。(可以根据测试类,根据我代码注释,从建表到更新,一个代码一个代码的放开;)
3.测试更新时,记得修改映射文件xxx.hbm.xml
4.根据表格中列出的映射属性,对应修改,可以看到对应的作用结果。