背景
现在的需求是根据类的文本文件获取类型,属性名称等信息创建数据库中的表。
重大意义:
把类转换成表并将数据插入数据库是一种对象关系映射(Object-Relational Mapping,ORM)的概念。在这种模式下,Java类与数据库表之间建立了映射关系,从而可以通过操作Java对象来实现对数据库的操作,而无需直接操作SQL语句。JdbcTemplate作为Spring Framework的一部分,可以与ORM框架如Hibernate、MyBatis等结合使用,实现这一目标。
以下是具体实现的步骤以及这种方式的巨大意义:
创建实体类: 首先,你会创建一个Java类,用于表示数据库中的表。通过在类上使用注解(如@Entity)来标记它们与数据库表之间的关联关系。
定义映射关系: 在实体类中,使用注解(如@Id、@Column等)来标识属性与表中列的映射关系。这样,你可以指定哪些属性对应表的哪些列,以及如何生成主键。
使用JdbcTemplate插入数据: 在Service类中,你可以使用JdbcTemplate的方法执行插入操作。这会自动将对象的属性映射到数据库表的列,并执行SQL插入语句。
巨大意义:
降低开发难度: ORM框架和JdbcTemplate使数据库操作变得更加抽象和简化,开发者无需编写大量的SQL语句,从而降低了开发的难度。
提高可维护性: 通过将类和数据库表进行映射,使得数据库结构变更时只需更新映射配置,而不需要大量修改代码。这提高了代码的可维护性。
增加代码可读性: 采用ORM和JdbcTemplate,数据库操作可以在代码中以类似面向对象的方式进行,使代码更具可读性和可理解性。
提升开发效率: 由于减少了编写和调试SQL语句的工作量,开发者可以更快地实现功能,从而提升开发效率。
防止SQL注入: 使用ORM框架和JdbcTemplate可以减少手动构建SQL语句的机会,从而降低了SQL注入的风险。
跨数据库兼容性: ORM框架和JdbcTemplate可以封装不同数据库的细节,从而使应用程序更容易迁移到不同的数据库平台上。
总之,将类转换成表并使用JdbcTemplate插入数据的方式在提高开发效率、降低维护成本、增强代码可读性和可维护性等方面都具有巨大的意义,尤其在大型应用程序开发中更为显著。
实操
创建表
大致思路:
将类中的属性名称类型等信息通过反射拿到,然后通过拼接字符串的形式变成sql语句,使用JDBCTemplate.excute 方法执行sql语句实现创表效果。
@Resource
private JdbcTemplate jdbcTemplate;
public static void main(String[] args) throws ClassNotFoundException {
String classPath = "com.tfjybj.service.User";
Class stu = Class.forName(classPath);
List fieldsList = new ArrayList<Field[]>(); // 保存属性对象数组到列表
while (stu != null) { // 遍历所有父类字节码对象
Field[] declaredFields = stu.getDeclaredFields(); // 获取字节码对象的属性对象数组
fieldsList.add(declaredFields);
stu = stu.getSuperclass(); // 获得父类的字节码对象
}
String classPathEnd = classPath.substring(classPath.lastIndexOf(".")+1);
StringBuffer stringSql = new StringBuffer();
stringSql.append("create table " + classPathEnd +"(\r\n") ;
String sqlFieldType = "";
String sqlFieldName = "";
for (Object fields:fieldsList) { // 打印当前类以及其父类的多有属性对象
Field[] f = (Field[]) fields;
for (Field field : f) {
String type = field.getType().toString();
String typeEnd = type.substring(type.lastIndexOf(".")+1);
System.out.println(typeEnd);
System.out.println(field.getName());
sqlFieldName = field.getName();
if(typeEnd == "String"){
sqlFieldType = "varchar(20)";
}else if(typeEnd =="Long")
{
sqlFieldType = "bigint(200)";
}else {
sqlFieldType = "varchar(20)";
}
stringSql.append(sqlFieldName+" "+sqlFieldType+","+"\r\n");
}
}
stringSql.deleteCharAt(stringSql.length()-3);
stringSql.append("\n)");
String strEnd = stringSql.toString();
System.out.println(strEnd);
jdbcTemplate.execute(stringSQL);
}
插入数据
实现思路:
insert 语句前边的属性 对应他真正的属性值 所以如何找对应关系 使用拼接字符串,找到get方法,反射出来对象对应的属性值。
Class detailClass = user.getClass();
List fieldsList = new ArrayList<Field[]>(); // 保存属性对象数组到列表
// while (detailClass != null) { // 遍历所有父类字节码对象
Field[] declaredFields = detailClass.getDeclaredFields(); // 获取字节码对象的属性对象数组
fieldsList.add(declaredFields);
// detailClass = detailClass.getSuperclass(); // 获得父类的字节码对象
// }
Map<String, String> map = new HashMap<>();
String className = detailClass.getName();
StringBuffer stringSql = new StringBuffer();
stringSql.append("insert into " + "user" + " (");
StringBuffer stringField = new StringBuffer();
StringBuffer strWhat = new StringBuffer();
StringBuffer endGoods = new StringBuffer();
String sqlFieldType = "";
String sqlFieldName = "";
String fieldName1 = "";
// String endGoods = "";
List<Object> args = new ArrayList<>();
for (Object fields : fieldsList)
{ // 打印当前类以及其父类的多有属性对象
Field[] f = (Field[]) fields;
for (Field field : f)
{
String fieldname = field.getName();
stringField.append(fieldname + ",");
strWhat.append("?" + ",");
fieldName1 = fieldname;
fieldName1 = fieldName1.substring(0, 1).toUpperCase() + fieldName1.substring(1);
String fieldMethod = "get" + fieldName1;
Method method = detailClass.getMethod(fieldMethod);
Object endThing = method.invoke(user);
endGoods.append("\"");
endGoods.append(endThing);
args.add(endThing);
endGoods.append("\"" + ",");
// endGoods.append("\"" + endGoods +"\""+",");
// map.put(fieldname,endThing.toString());
}
}
stringField.deleteCharAt(stringField.length() - 1);
endGoods.deleteCharAt(endGoods.length() - 1);
stringSql.append(stringField);
stringSql.append(")");
strWhat.deleteCharAt(strWhat.length() - 1);
stringSql.append(" values " + "(");
stringSql.append(strWhat);
stringSql.append(")");
System.out.println(stringSql.toString());
System.out.println(endGoods.toString());
String endGoodsStr = endGoods.toString();
endGoodsStr = endGoodsStr.substring(1, endGoodsStr.length() - 1);
List<String> detailValueList = new ArrayList<>();
// String detailValue =
// String insertSql =
// //首先拼接好所有的sql
// //拼接好入参
// //进行调用
//
String sql = stringSql.toString();
System.out.println(sql);
// args[0]= "aaa";
// System.out.println(args);
// //参数一:插入数据的SQL语句,参数二:对应SQL语句中占位符?的参数
return jdbcTemplate.update(sql, args.toArray());
}
注意:
使用JDBCTemplate插入记录的时候遇见这样一个问题,要传数组,但是我传的是一个字符串。所以调用JDBCTemplate方法的时候会报错。
报找不到第二个参数。
下边是可以的。
最终发现传入的是字符串,而不是一个数组。
代码做和如下改动:
就能插库了。
总结
在使用Spring的JdbcTemplate来将类转换成表并插入数据时,需要定义实体类与数据库表之间的映射关系,并使用JdbcTemplate执行插入操作。以下是一个示例,演示如何解决这个问题:
假设我们有一个实体类User,对应数据库中的users表,表结构如下:
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);
首先,我们需要定义User类,该类的字段与表的列对应:
public class User {
private int id;
private String username;
private String email;
// 构造函数、getter和setter等方法省略
}
接下来,我们使用JdbcTemplate来将类转换成表并插入数据:
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
public class UserDao {
private final JdbcTemplate jdbcTemplate;
public UserDao(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public void saveUser(User user) {
String sql = "INSERT INTO users (id, username, email) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, user.getId(), user.getUsername(), user.getEmail());
}
}
在这里,我们创建了一个UserDao类,其中的saveUser方法用于将User类对象插入到数据库中。我们使用JdbcTemplate的update方法执行插入操作,传递SQL语句和对应的参数。JdbcTemplate会自动将实体类的字段映射到数据库表的列,并插入相应的数据。
为了使用上述UserDao类,我们需要配置数据源(DataSource),并将其注入到UserDao中。在Spring配置文件中,我们可以这样定义数据源和JdbcTemplate:
<!-- 数据源配置 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydb" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<!-- JdbcTemplate配置 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
然后,我们在应用代码中可以使用UserDao来插入数据:
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = context.getBean(UserDao.class);
User user = new User();
user.setId(1);
user.setUsername("john_doe");
user.setEmail("john@example.com");
userDao.saveUser(user);
}
}
通过上述配置和代码,我们可以使用JdbcTemplate将类转换成表并插入数据。在实际应用中,通常会根据实际需求,定义更多的CRUD操作,并在Service或Repository层中调用相应的DAO来操作数据库。