一,我们来模拟hibernate的实现,首先模拟hibernate中的Session对象建立一个Session类,代码如下:
public void save(Student s) throws Exception {
String sql = createSQL();
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/hibernate","root","root");
PreparedStatement ps = conn.prepareStatement(sql);
for(int i=0;i<methodNames.length;i++){
Method m = s.getClass().getMethod(methodNames[i]);
Class r = m.getReturnType();
if(r.getName().equals("java.lang.String")){
String returnValue = (String)m.invoke(s);
ps.setString(i+1, returnValue);
}
if(r.getName().equals("int")){
Integer returnValue = (Integer)m.invoke(s);
ps.setInt(i+1, returnValue);
}
}
ps.executeUpdate();
ps.close();
conn.close();
}
private String createSQL() {
String str1 = "";
String str2 = "";
int index = 0;
for(String s:cfs.keySet()){
String v = cfs.get(s);
v = Character.toUpperCase(v.charAt(0)) + v.substring(1);
methodNames[index] = "get" + v;
System.out.println(methodNames[index]);
str1 += s + ",";
index++;
}
str1 = str1.substring(0,str1.length()-1);
for(int i=0;i<cfs.size();i++){
str2 += "?,";
}
str2 = str2.substring(0,str2.length()-1);
String sql = "insert into "+tableName+"(" + str1 + ")" + " values(" + str2 +");";
System.out.println(sql);
return sql;
}
}
这里用到了java的反射机制,首先建立一个Map存入对应的字段名和属性名,从中取出对应的字段名拼成sql语句,然后用了PreparedStatement,后面?中的内容用到了反射。
if(r.getName().equals("java.lang.String")){
String returnValue = (String)m.invoke(s);
ps.setString(i+1, returnValue);
}
对应的测试类代码如下:
public class StudentTest {
public static void main(String[]args) throws Exception{
Student s = new Student();
s.setId(2);
s.setName("s2");
s.setAge(2);
Session session = new Session();
session.save(s);
}
}
二,Hibernate基础配置
Hibernate.cfg.xml:hbm2ddl.auto
在SessionFactory创建时,自动检查数据库结构,或者将数据库schema的DDL导出到数据库. 使用 create-drop时,在显式关闭SessionFactory时,将drop掉数据库schema. 取值 validate | update | create | create-drop
搭建日志环境并配置显示DDL语句
我们使用slf接口,然后使用log4j的实现(其实也可以用slf4j nodep,jdk logging api,apach commons-logging)。
1、 首先引入log4j的jar包(log4j-1.2.14.jar),
2、 然后再引入slf4j实现LOG4J和适配器jar包(slf4j-log4j12-1.5.8.jar)
3、 最后创建log4j的配置文件(log4j.properties),并加以修改,只要保留
log4j.logger.org.hibernate.tool.hbm2ddl=debug
搭建Junit环境
1、首先引入Junit 类库 jar包 (junit-4.8.1.jar)
2、在项目名上右键→new→Source Folder→输入名称→finish
3、注意,你对哪个包进行测试,你就在测试下建立和那个包相同的包
4、建立测试类,需要在测试的方法前面加入”@Test”
public class TeacherTest {
private static SessionFactory sf = null;
@BeforeClass//表示Junit此类被加载到内存中就执行这个方法
public static void beforClass(){
sf = new AnnotationConfiguration().configure().buildSessionFactory();
}
@Test//表示下面的方法是测试用的。
public void testTeacherSave(){
Teacher t = new Teacher();
t.setId(6);
t.setName("s1");
t.setTitle("中级");
Session session = sf.openSession();
session.beginTransaction();
session.save(t);
session.getTransaction().commit();
session.close();
}
@AfterClass//Junit在类结果时,自动关闭
public static void afterClass(){
sf.close();
}}
Annotation
一、 表名和类名不同,对表名进行配置
Annotation:使用 @Table(name=”tableName”) 进行注解
/**
* @Entity 表示下面的这个Teacher是一个实体类
* @Table 表示映射到数据表中的表名,其中的name参数表示"表名称"
* @Id 表示主键Id,一般放在getXXX前面
*/
@Entity
@Table(name="_teacher")
public class Teacher {
[……]
}
Xml:
<class name="Student" table="_student">
二、 字段名和属性相同
Annotation:默认为@Basic
注意:如果在成员属性没有加入任何注解,则默认在前面加入了@Basic
Xml中不用写column
三、 字段名和属性名不同
Annotation:使用@Column(name=”columnName”)进行注解
例如:
/**
* @Entity 表示下面的这个Teacher是一个实体类
* @Table 表示映射到数据表中的表名,其中的name参数表示"表名称"
* @Column 表示实体类成员属性映射数据表中的字段名,其中name参数指定一个新的字段名
* @Id 表示主键Id
*/
@Entity
@Table(name="_teacher")
public class Teacher {
private int id;
private String name;
private String title;
//设置主键使用@Id
@Id
public int getId() {
return id;
}
@Column(name="_name")//字段名与属性不同时
public String getName() {
return name;
}}
Xml:
<property name="name" column="_name"/>
四、 不需要(持久化)psersistence的字段(不重要)
就是不实体类的某个成员属性不需要存入数据库中
Annotation:使用@Transient 进行注解就可以了。
例如:
@Transient
public String getTitle() {
return title;
}
Xml:不写(就是不需要对这个成员属性进行映射)
五、 映射日期与时间类型,指定时间精度(不重要)
Annotation:使用@Temporal(value=TemporalType)来注解表示日期和时间的注解
其中TemporalType有三个值:TemporalType.TIMESTAMP 表示yyyy-MM-dd HH:mm:ss
TemporalType.DATE表示yyyy-MM-dd
TemporalType.TIME表示HH:mm:ss
@Temporal(value=TemporalType.DATE)
public Date getBirthDate() {
return birthDate;
}
注意:当使用注解时,属性为value时,则这个属性名可以省略,例如:@Temporal(TemporalType)
Xml:使用type属性指定hibernate类型
<property name="birthDate" type="date"/>
注意:hibernate日期时间类型有:date, time, timestamp,当然您也可以使用Java包装类。