将主键所对应的属性提取出一个类(称之为主键类),并且主键类需要实现Serializable接口,
hinernate.cfg.xml
建表类:CreateTable.java
如果执行两次相同的保存操作,会报主键相同的错误,因为这时候主键已经不是hibernate自动生成了,而是我们根据自己的业务 逻辑自己定义的
重写equals方法和hashCode 方法,原因同联合主键一:普通方式
场景和联合主键一:普通方式相同,只不过该方法将主键单独抽取为一个类,当然在配置文件时需要有所改变,个人感觉该方法比较好
主键类:StudentPrimaryKey.java
package com.fgh.hibernate;
import java.io.Serializable;
/**
* Student 主键类
*
* @author fgh
*
*/
public class StudentPrimaryKey implements Serializable {
private static final long serialVersionUID = 5129414054059220497L;
private String cardId;
private String name;
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cardId == null) ? 0 : cardId.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final StudentPrimaryKey other = (StudentPrimaryKey) obj;
if (cardId == null) {
if (other.cardId != null)
return false;
} else if (!cardId.equals(other.cardId))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
学生类:Student.java
package com.fgh.hibernate;
/**
*
* @author fgh
*
*/
public class Student {
//主键类的引用
private StudentPrimaryKey studentPrimaryKey;
private int age;
public StudentPrimaryKey getStudentPrimaryKey() {
return studentPrimaryKey;
}
public void setStudentPrimaryKey(StudentPrimaryKey studentPrimaryKey) {
this.studentPrimaryKey = studentPrimaryKey;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Student.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">
<hibernate-mapping>
<class name="com.fgh.hibernate.Student" table="student_composite">
<!-- 组件映射 使用class属性指定主键类 这里一定要指定好 name属性 否则找不到主键 -->
<composite-id name="studentPrimaryKey"
class="com.fgh.hibernate.StudentPrimaryKey">
<key-property name="cardId" column="cardId" type="string"></key-property>
<key-property name="name" column="name" type="string"></key-property>
</composite-id>
<property name="age" column="age" type="int"></property>
</class>
</hibernate-mapping>
hinernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="connection.url">
jdbc:mysql://localhost:3306/hibernate
</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="show_sql">true</property>
<mapping resource="Student.hbm.xml" />
</session-factory>
</hibernate-configuration>
建表类:CreateTable.java
package com.fgh.hibernate;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
public class CreateTable {
public static void main(String[] args) {
SchemaExport export = new SchemaExport(new Configuration().configure());
export.create(true, true);
}
}
测试类:hibernateTest.java
package com.fgh.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
/**
* 联合主键二
*
* @author fgh
*
*/
public class HibernateTest {
private static SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure()
.buildSessionFactory();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
// 保存-------begin-------
StudentPrimaryKey studentPrimaryKey = new StudentPrimaryKey();
studentPrimaryKey.setCardId("123");
studentPrimaryKey.setName("zhangsan");
Student student = new Student();
student.setStudentPrimaryKey(studentPrimaryKey);
student.setAge(20);
session.save(student);
// 保存-------end-------
// 查询 -------begin------
// Student student = (Student)
// session.get(Student.class,studentPrimaryKey);
// System.out.println(student.getAge());
// 查询 -------end------
tx.commit();
} catch (Exception e) {
e.printStackTrace();
if (null != tx) {
tx.rollback();
}
} finally {
session.close();
}
}
}
如果执行两次相同的保存操作,会报主键相同的错误,因为这时候主键已经不是hibernate自动生成了,而是我们根据自己的业务 逻辑自己定义的
报错信息:
Hibernate: insert into student_composite (age, cardId, name) values (?, ?, ?)
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at com.fgh.hibernate.HibernateTest.main(HibernateTest.java:46)
Caused by: java.sql.BatchUpdateException: Duplicate entry '123-zhangsan' for key 'PRIMARY'
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1693)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1108)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
... 8 more
Thanks,it's over,I hope for your help!