Hibernate入门----几种主键ID生成方式及示例【第二天】
Hibernate主键ID生成方式
1、assigned生成方式:【手动生成】
<另:在用Hibernate的时候,当有表中的主键是库自动生成的时候将使用native。而当是自己添加的时候则需要改为assigned。否则将会出现异常!>
即主键由外部程序负责生成,无需Hibernate参与,即当增加一个实例时,由程序设定该实体的ID值(手工分配值)
即在映射文件中如下增加:
<generator class="assigned"></generator>
而增加记录的类里给其赋ID值。
2、identity生成方式:【MYSQL自增】
在DB、SQL Server、MySql等数据库产品表中主键可以设定自动增长列,则增加一条记录时主键的值可以不赋值。
用数据库的主键生成机制:数据库表创建时加:auto_increment。
表映射文件:
<generator class="identity"></generator>
在操作实体以及实体类中无需体现ID主键。
3、increment生成方式:【实例自增-避免使用】
主键按数值顺序递增-------尽量避免使用该方法。多个实例操作数据库时,会造成主键重复现象
表映射:
<generator class="increment"></generator>
4、sequence生成方式:【Oracle自生】
采用数据库提供的sequence机制生成主键,如Oracle数据库。
表映射:
<generator class="sequence"></generator>
5、uuid.hex生成方式:【依据机器标识等自生】
由Hibernate为ID列赋值,依据当前客户端机器的IP、JVM启动时间、当前时间、一个机器数生成串、以该串为ID值。
表映射:
<generator class="uuid.hex"></generator>
注意:以上方法建议都掌握牢记原理
实例一:assigned生成方式:【手动生成】-----之前的文章已有
实例二、identity生成方式:【MYSQL自增】
一、在原来的hibernate.cfg.xml文件中,记得加入:
表的映射文件记录。即:
<mapping resource="resource/Customer2.hbm.xml"/>
完整代码:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <!-- 配置文件标签顺序property*,mapping*,(class-cache|collection-cache),event,listener* --> <session-factory> <!-- 设置访问mysql数据库的驱动描述 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 设置数据库的url --> <property name="connection.url">jdbc:mysql://127.0.0.1:3306/test</property> <!-- 指定登录数据库用户账户 --> <property name="connection.username">root</property> <!-- 指定登录数据库用户密码 --> <property name="connection.password">123456</property> <!-- 设置访问数据库的方言,提高数据库访问性能 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 设置ddl --> <!-- <property name="hbm2ddl.auto">auto</property> --> <!-- 配置控制台视图,显示查询内容 --> <property name="show_sql">true</property> <!-- 下面是多表映射 --> <!-- 映射表文件 --> <mapping resource="resource/Customer.hbm.xml"/> <!-- 映射表文件 --> <mapping resource="resource/Customer2.hbm.xml"/> </session-factory> </hibernate-configuration>
二、新建表映射表文件(Customer2.hbm.xml)
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="bean" auto-import="false"> <!-- POJO类映射表及某表的关系--> <class name="bean.Customer2" table="customers2" catalog="test"> <id name="customerID" type="java.lang.Integer"> <column name="customerID"/> <generator class="identity"></generator> </id> <!-- 映射表中name字段 --> <property name="name" type="java.lang.String"> <column name="name" length="40"/> </property> <!-- 映射表中phone字段 --> <property name="phone" type="java.lang.String"> <column name="phone" length="16"/> </property> </class> </hibernate-mapping>
悟:该文件主要改<generator class="identity"></generator>,后续主键生成方式。字段根据表来即可。
二、将之前的HibernateSessionFactory类拿来使用:【代码复用】
package bean; import java.util.List; import hibernate.factory.HibernateSessionFactory; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.query.Query; //用于测试identity主键生成方式,增加记录 //由于是增加数据,所以不需要写Query,只需要new表,增加数据即可 public class Customer2Demo { Session session = HibernateSessionFactory.getSession(); Transaction tran = session.beginTransaction(); public static void main(String[] args) { //测试identity主键生成 Customer2Demo demo = new Customer2Demo(); Customer2 customer2 = new Customer2(); demo.saveCustomer2IDByIdentity(customer2, "华山", "580"); //测试查询结果 List list = demo.queryAllCustomer2(); for (int i = 0; i < list.size(); i++) { Customer2 customer = (Customer2)list.get(i); System.out.println(customer.getCustomerID()+customer.getName()+customer.getPhone()); } HibernateSessionFactory.closeSession(); } //下面是封装保存 public void saveCustomer2IDByIdentity(Customer2 customer2,String name,String phone) { customer2.setName(name); customer2.setPhone(phone); session.save(customer2); //一定一定要记得提交事务 tran.commit(); } //下面是封装查询 @SuppressWarnings("rawtypes") public List queryAllCustomer2(){ /**由会话工厂类创建一个会话Session对象**/ Session session = HibernateSessionFactory.getSession(); /**由会话session对象创建一个查询对象**/ Query query = session.createQuery("from bean.Customer2"); List list = query.list(); HibernateSessionFactory.closeSession(); return list; } }
三、新建映射表类:Customer2.java
package bean; //验证identity生成主键方式的映射类,数据库对应表customers2 public class Customer2 { private int customerID; private String name,phone; public int getCustomerID() { return customerID; } public void setCustomerID(int customerID) { this.customerID = customerID; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
四、测试类:【顺便查询结果,看是否成功】
package bean; import java.util.List; import hibernate.factory.HibernateSessionFactory; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.query.Query; //用于测试identity主键生成方式,增加记录 //由于是增加数据,所以不需要写Query,只需要new表,增加数据即可 public class Customer2Demo { Session session = HibernateSessionFactory.getSession(); Transaction tran = session.beginTransaction(); public static void main(String[] args) { //测试identity主键生成 Customer2Demo demo = new Customer2Demo(); Customer2 customer2 = new Customer2(); demo.saveCustomer2IDByIdentity(customer2, "华山", "580"); //测试查询结果 List list = demo.queryAllCustomer2(); for (int i = 0; i < list.size(); i++) { Customer2 customer = (Customer2)list.get(i); System.out.println(customer.getCustomerID()+customer.getName()+customer.getPhone()); } HibernateSessionFactory.closeSession(); } //下面是封装保存 public void saveCustomer2IDByIdentity(Customer2 customer2,String name,String phone) { customer2.setName(name); customer2.setPhone(phone); session.save(customer2); //一定一定要记得提交事务 tran.commit(); } //下面是封装查询 @SuppressWarnings("rawtypes") public List queryAllCustomer2(){ /**由会话工厂类创建一个会话Session对象**/ Session session = HibernateSessionFactory.getSession(); /**由会话session对象创建一个查询对象**/ Query query = session.createQuery("from bean.Customer2"); List list = query.list(); HibernateSessionFactory.closeSession(); return list; } }
悟:在编写程序过程中,代码复用很重要,同时,考虑减少代码量,但减少代码量的时候应该考虑减少代码是否会造成后续不可用,该不该较少等。如四中,设置了一个全局对象session,后续查询的方法中,直接使用该对象是不可行的,而是重新获得,这是为什么呢?
个人思考:
一、在提交事务保存的时候,会话会被清空,从而造成后续使用问题。
二、后续封装的方法尽量不使用全局变量或者对象,使之分工明确。
其他注意:在数据库没有设定ID自增时,会报如下错误。
数据库修改设置字段自增:
alter table customers2 auto_increment=初始值;