Hibernate--根据实体类获得表名、主键名、字段名(与Spring集成)(二)

在上一篇中,我们创建了HibernateConfigurationUtil类,可以通过它来获得实体类对应的表名、列名等相关信息,本篇我们会就借助于HibernateConfigurationUtil类以及Java反射,来实现一个JDBCUitl工具类,实现类似于Hibernate中Session.save(Object object)的功能

JDBCUtil类

package util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class JDBCUtil {

	/**
	 * 利用反射+JDBC实现类似于Session.save(Object object)的操作,适用于主键为单一自增主键
	 * 这里只是提供一种实现思路,可以根据需要进行扩展以及实现类似的update、delete、get操作
	 *
	 * @param connection 数据库连接
	 * @param entity 要保存的实体类
	 * @throws Exception
	 */
	public static <T> void save(Connection connection, T entity)
			throws Exception {
		Class<? extends Object> clazz = entity.getClass();
		Field[] fields = clazz.getDeclaredFields();
		StringBuilder builder = new StringBuilder();
		builder.append("insert into ");
		builder.append(HibernateConfigurationUtil.getTableName(clazz));
		builder.append(" (");

		List<Field> useFields = new ArrayList<Field>();
		Field field = null;

		for (int i = 0; i < fields.length; i++) {
			//设置字段可以被访问,如果不设置此选项就无法访问private字段
			field = fields[i];
			field.setAccessible(true);
			// 过滤不需要的属性,
			if ("id".equals(field.getName())) {
				continue;
			}
			useFields.add(field);
			builder.append(HibernateConfigurationUtil.getColumnName(clazz,
					field.getName()));
			if (i < fields.length - 1)
				builder.append(", ");
		}
		builder.append(") values (");
		for (int i = 0; i < useFields.size(); i++) {
			builder.append(" ?");
			if (i < useFields.size() - 1) {
				builder.append(", ");
			} else {
				builder.append(" )");
			}
		}
		PreparedStatement pstmt = connection.prepareStatement(builder
				.toString());
		Class<?> clazz2 = null;
		for (int i = 0; i < useFields.size(); i++) {
			field = useFields.get(i);
			// 根据字段的类型设置对应类型的值
			clazz2 = field.getType();
			if (clazz2 == String.class) {
				pstmt.setString(i + 1, field.get(entity).toString());
				continue;
			}
			if (clazz2 == Integer.class || clazz2 == int.class) {
				pstmt.setInt(i + 1, field.getInt(entity));
				continue;
			}
			if (clazz2 == Double.class || clazz2 == double.class) {
				pstmt.setDouble(i + 1, field.getDouble(entity));
				continue;
			}
			if (clazz2 == Date.class) {
				Date date = (Date) field.get(entity);
				pstmt.setTimestamp(i+1, new Timestamp(date.getTime()));
				continue;
			}
		}
		pstmt.executeUpdate();
	}
}

User类

package bean;

import java.util.Date;

public class User {

	private int id;

	private String username;

	private String password;

	private int intValue;

	private double doubleValue;

	private Date dateValue;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getIntValue() {
		return intValue;
	}

	public void setIntValue(int intValue) {
		this.intValue = intValue;
	}

	public double getDoubleValue() {
		return doubleValue;
	}

	public void setDoubleValue(double doubleValue) {
		this.doubleValue = doubleValue;
	}

	public Date getDateValue() {
		return dateValue;
	}

	public void setDateValue(Date dateValue) {
		this.dateValue = dateValue;
	}

}

User.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>
	<class name="bean.User" table="_user">
		<id name="id" type="int">
			<column name="id" />
			<generator class="identity" />
		</id>
		<property name="username" type="string">
			<column name="_username" />
		</property>
		<property name="password" type="string">
			<column name="_password" />
		</property>
		<property name="intValue" type="int">
			<column name="_intValue" />
		</property>
		<property name="doubleValue" type="double">
			<column name="_doubleValue" />
		</property>
		<property name="dateValue" type="timestamp">
			<column name="_dateValue" />
		</property>
	</class>
</hibernate-mapping>

UserDao

package dao;

import bean.User;

public interface UserDao {
	public void addUser(User user);
}

UserDaoImpl

package dao.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.Work;

import util.JDBCUtil;
import bean.User;
import dao.UserDao;

public class UserDaoImpl implements UserDao {

	private SessionFactory sessionFactory;

	@Override
	public void addUser(final User user) {
		Session session = sessionFactory.getCurrentSession();
		session.doWork(new Work() {
			@Override
			public void execute(Connection connection) throws SQLException {

				try {
					JDBCUtil.save(connection, user);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

}

applicationContext.xml

注意:在Hibernate4中必须要配置事务,否则上面的sessionFactory.getCurrentSession()将无法取到值

<bean id="sessionFactory"
		class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>bean/User.hbm.xml</value>
			</list>
		</property>
	</bean>

	<!-- 配置事务 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate4.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>

	<!-- 配置事务的传播特性 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="del*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="*" read-only="true" />
		</tx:attributes>
	</tx:advice>

	<!-- 配置参与事务的类和方法 -->
	<aop:config>
		<aop:pointcut expression="execution(* dao.impl.*.*(..))"
			id="allServiceMethod" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethod" />
	</aop:config>

	<bean id="userDao" class="dao.impl.UserDaoImpl">
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
	

下面是测试代码:

package test;

import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import bean.User;

import dao.UserDao;

public class TestJDBCUtil {
	@SuppressWarnings("resource")
	public static void main(String[] args) {

		ApplicationContext context =  new ClassPathXmlApplicationContext("applicationContext.xml");
		UserDao userDao = (UserDao) context.getBean("userDao");
		User user = new User();
		user.setUsername("name");
		user.setPassword("password");
		user.setIntValue(2);
		user.setDoubleValue(4.0);
		user.setDateValue(new Date());
		userDao.addUser(user);
	}
}

注:所使用的数据库为mysql,Hibernate版本为4.2.12.Final

时间: 2024-09-29 22:06:09

Hibernate--根据实体类获得表名、主键名、字段名(与Spring集成)(二)的相关文章

hibernate注解实体类

只要在hibernate.cfg.xml里加上如下代码 <property name="hbm2ddl.auto">update</property> validate               加载hibernate时,验证创建数据库表结构 create                  每次加载hibernate,重新创建数据库表结构 create-drop        加载hibernate时创建,退出是删除表结构 update            

Hibernate实体类编写规则和主键策略

一.实体类的编写规则 1.属性要是私有的. 2.要有公开的setter和getter方法供外界访问和修改. 3.每一个实体类要有一个属性作为唯一值(一般都是使用对于数据表的主键). 4.建议数据类型不要使用基本的数据类型,而是使用相应的包装类. 5.Java中对应的包装类 基本数据类型 对应包装类 int Integer char Character boolean Boolean float Float double Double short Short long Long byte Byte

Hibernate之实体类配置

1.@Column属性 (1)设置字段属性唯一 @Column(unique=true) private String name; Done Hibernate之实体类配置

Hibernate之实体类设计基本步骤

1.先设计一个基类BaseBean (1)@MappedSuperclass表示实体类父类 package com.life.hibernate.bean; import java.util.Date; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Temporal; im

如何使用sqlalchemy获取表的主键、以及每一个字段名

使用sqlalchemy获取到的结果只包含数据,不包含字段,那么我们如何获取到对应字段呢?以及如何获取某张表的主键呢? from sqlalchemy.ext.automap import automap_base from sqlalchemy.orm import sessionmaker from sqlalchemy import MetaData, inspect, create_engine engine = create_engine("postgresql://postgres:

《Hibernate学习笔记之三》:联合主键的映射

<Hibernate学习笔记之三>:联合主键的映射 就如在前面所举的例子一样,是使用的id作为唯一的主键,一般情况下我们也只使用唯一的一个属性作为主键,但是在实际中,我们可能会遇到几个属性作为主键的情况,因此,在本篇博文中,就来介绍下,联合主键的映射关系应该如何来做?? 联合主键的映射有两种方式来进行实现. 1.使用映射文件 XXX.bhm.xml 2.使用Annotation Hibernate首先需要使用联合主键的实体类必须实现Serializable接口,即为了使序列能够被序列化进行传输

Hibernate学习笔记(5)联合主键

现在大家都不推荐使用联合主键,关键是因为其需要自己手工维护,比较麻烦.但是一个项目可能因为历史遗留原因,你不得不面对联合主键. Hibernate联合主键问题解决如下: 可以使用一个组件作为一个实体类的标识符.你的组件类必须满足以下要求: (1)它必须实现 java.io.Serializable 接口 (2)它必须重新实现 equals() 和 hashCode() 方法,始终和组合关键字在数据库中的概念保持一致 注意:在 Hibernate3 中,第二个要求并非是 Hibernate 强制必

创建表 添加主键 添加列常用SQL语句

--删除主键 alter table 表名 drop constraint 主键名--添加主键alter table 表名 add constraint 主键名 primary key(字段名1,字段名2……)--添加非聚集索引的主键alter table 表名 add constraint 主键名 primary key NONCLUSTERED(字段名1,字段名2……) 新建表: create table [表名] ( [自动编号字段] int IDENTITY (1,1) PRIMARY

SQL Server 创建表 添加主键 添加列常用SQL语句

--删除主键 alter table 表名 drop constraint 主键名 --添加主键 alter table 表名 add constraint 主键名 primary key(字段名1,字段名2……) --添加非聚集索引的主键 alter table 表名 add constraint 主键名 primary key NONCLUSTERED(字段名1,字段名2……) 新建表: create table [表名] ( [自动编号字段] int IDENTITY (1,1) PRIM

SQL Server 创建表 添加主键 添加列常用SQL语句【转】

--删除主键alter table 表名 drop constraint 主键名--添加主键alter table 表名 add constraint 主键名 primary key(字段名1,字段名2……)--添加非聚集索引的主键alter table 表名 add constraint 主键名 primary key NONCLUSTERED(字段名1,字段名2……) 新建表: create table [表名] ( [自动编号字段] int IDENTITY (1,1) PRIMARY K