程序员必知:关于高淇JAVA中SORM总结学习笔记详细个人解释

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 程序员必知:关于高淇JAVA中SORM总结学习笔记详细个人解释

代码来源于高淇JAVA教学视频 谢谢高淇老师的教学。

因为自己在学习的过程中发现了很多困难点,总结下希望对自己接下来学框架提升。给像我一样得初学者方便。

SORM框架是一个简单的ORM,关系对象映射,可以通过这个框架方便的更改和操作一些数据库的东西,在框架运行的时候也会根据数据库中的表生成相应的Javabean在po包下。通过直接对po包下的操作在运用query中的一些操作就可以实现对数据库的操作。思路会在代码中注释。

QueryFactory直接生产出Query给用的人调用,Query作为一个接口是更好的让多种数据库提供各自的操作。实现mySQLQuery或者OracleQuery,conventor是个转换不同语言数据类型的工具

TableContext就是核心的程序连接数据库表的类。DBManager钟放的是一些配置资源文件和一些加载处理。

明确主要思路,就是通过factory制作一个query,然后直接set方法然后将对象传入query的方法实现功能。查询的话也是通过queryrows方法传入select语句进行查询,因为查询语句的多样性简单的框架没有进一步封装。

先从最底层的tablecontext和DBManage说起:

解释会在代码中标识

public class DBManager {

private static Configuration conf;               //这是在bean包下定义的一个类用来把从配置文件提取出来方便用get set

private static List pool=new ArrayList();      //这是连接池的定义,我在老师的基础上做了些更改,我把连接池全部放到了这个类里

static{                                      //静态代码块初始化资源文件中的数据, 注意静态块是和类一起加载的,大量用静态影响内存

Properties pro=new Properties();                      //这个类是用来从资源文件中提取数据的类

try {

pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("database.properties"));

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

conf=new Configuration();

conf.setDriver(pro.getProperty("driver"));

conf.setPoPackage(pro.getProperty("poPackage"));

conf.setPwd(pro.getProperty("pwd"));

conf.setScrPath(pro.getProperty("srcPath"));

conf.setUser(pro.getProperty("user"));

conf.setUrl(pro.getProperty("url"));

conf.setUsingDB(pro.getProperty("usingDB"));

conf.setQueryClass(pro.getProperty("queryClass"));

conf.setMAX_POOL(Integer.parseInt(pro.getProperty("max_pool")));

conf.setMIN_POOL(Integer.parseInt(pro.getProperty("min_pool")));

System.out.println(TableContext.class);//加载类                          //这是用来加载表信息的,用于表连接也可以用反射来加载,但是要trycatch选择输出加载

initPool();                                              //加载连接池

}

public static void initPool(){                          //连接池的初始化

if(pool==null){

pool=new ArrayList();

}

while(pool.size()[span style="color: rgba(0, 0, 0, 1)">conf.getMIN_POOL()){

pool.add(DBManager.createConn());

//初始化

}

}

public static Connection getConn(){ //连接池取连接

int last_index=pool.size()-1;

Connection conn=pool.get(last_index);

pool.remove(last_index);

return conn;

}

public static void CloseConn(Connection conn){                          //连接池关闭

if(pool.size()>conf.getMAX_POOL()){

try {

conn.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}else {

pool.add(conn);

}

}

public static Connection createConn(){

try {                                                //真正的建立一个连接

Class.forName(conf.getDriver());

//代码效果参考:http://www.zidongmutanji.com/bxxx/453368.html

return DriverManager.getConnection(conf.getUrl(),conf.getUser(),conf.getPwd());

//直接建立连接

} catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

return null;

}

}

                                                     //get用于配置信息的哪个类,很好理解

public static Configuration getConf(){

return conf;

}

                                                    //之后的关闭就不说了,主要是要记得把关闭改变成从线程池中假关闭

public static void close(ResultSet rs,Statement ps,Connection conn){

try {

if(rs!=null){

rs.close();

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

try {

if(ps!=null){

ps.close();

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

try {

if(conn!=null){

CloseConn(conn);

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public static void close(Statement ps,Connection conn){

try {

if(ps!=null){

ps.close();

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

try {

if(conn!=null){

CloseConn(conn);

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

然后现在有配置文件和连接了

接下来是表连接tablecontect

/

管理数据库所有表结构和类结构的关系,并可以根据表结构生成类结构

@author NodeRed

*/

public class TableContext { //最核心的 可以根据表生成类。

/

表名为key,信息对对象为value

/

public static Map tables=new HashMap(); //这个表中的tableInfo也是定义的一个类大概意思就是能够记录下整张表,这里这个map就能记录整个database

/

将po的class对象和表关联

/

public static Map poClassTableMap=new HashMap(); //这个表用来记录这个表后来会产生哪个类,这后面会说

private TableContext(){};

//无参构造很重要

static{

try {

Connection con=DBManager.getConn(); //这里就获得了和数据库的连接了

DatabaseMetaData dbmd=con.getMetaData(); //这里原视频中没有说,大概是 可以从连接中搜索获取一些元数据,%是类似所有

ResultSet tableRet=dbmd.getTables(null, "%", "%",new String【】{"TABLE"}); //TABLE那就是要查询的就是表了,但是这里出现了问题,意外的搜索出了创建表的时间

System.out.println(tableRet); //记录的那个表,捯饬了半天也没解决。 然后之后是放到了一个结果集里

while(tableRet.next()){ //遍历查找出来的结果

String tableName=(String)tableRet.getObject("TABLE_NAME"); //获得表名

TableInfo ti=new TableInfo(tableName, new ArrayList(), // 然后把表名先把上说的可以记录下整个表的new出来,具体的后面再说

new HashMap());

tables.put(tableName, ti); //放到记录整个数据库的那个表里

ResultSet set=dbmd.getColumns(null, "%", tableName ,"%"); //这里根据表名获取字段集,

while(set.next()){

ColumnInFo ci=new ColumnInFo(set.getString("COLUMN_NAME"),set.getString("TYPE_NAME"),0);//可以看出这里获取了字段的名字和类型

ti.getColumns().put(set.getString("COLUMN_NAME"),ci); //这里是放到表映射,加载表的字段

}

ResultSet set2=dbmd.getPrimaryKeys(null, "%", tableName);

while(set2.next()){   //这里加载主键

ColumnInFo ci2=(ColumnInFo)ti.getColumns().get(set2.getObject("COLUMN_NAME"));

ci2.setKeyType(1);

ti.getPriKeys().add(ci2);

}

if(ti.getPriKeys().size()>0){

ti.setOnlyPrivate(ti.getPriKeys().get(0));

}

}                                  //如果这里没有懂得话,不要急,后面结合javabean

//这里就可以理解为,你在java中建立了一个表格,不是完全填好数据得表格,只是单纯得有每个数据类型在哪个表是不是主键得表示

有了这个标识以后可以在query中找出数据库要操作得是哪个,再从query中操作数据库。

} catch (Exception e) {

// TODO: handle exception

}

updataJavaPOFile();                        //因为我们要再数据库中操作,程序事先是不知道你表中得每一项叫什么名字就没办法根据数据可定义好类,在用类来操作数据库                        

loadPOTables(); //这里我们就可以根据数据库中获取的表框架,获取表的名字,表中字段类型,生成这个数据库的java类

//然后是每次加载这个类的时候更新

}  

//一下是实现方法

public static void updataJavaPOFile(){

Map map= TableContext.tables; 这里就通过这个tables表然后用后面的一个java类实现了在项目中构造java类

// TableInfo t=map.get("new_table");

for(TableInfo t:map.values()){

JavaFileUtils.createJavaPOFile(t, new MysqlTypeConventor());

}

}

public static void loadPOTables(){

// Class c=Class.forName("com.cy.sorm.New_table");

// poClassTableMap.put(c, TableInfo); //这里就是用反射把这个类和产生自哪个表放在了一个表里,在后面的操作有用

for(TableInfo tableInfo:tables.values()){

try{

Class c=Class.forName(DBManager.getConf().getPoPackage()+

"."+StringUTils.firstChar2UpCase(tableInfo.getTname()));

poClassTableMap.put(c, tableInfo);

}catch(Exception e){

e.printStackTrace();

}

}

}

// public static void main(String【】 args) {

// Map tables=TableContext.tables;

// System.out.println(tables);

// }

}

 这里也是orm的核心了,从数据库中复制了一个映射表过来。但是老师说在工作中用的很少。接下来说一下字段映射和表映射吧,可以从以上的javabean包中可以看出,除了很容易理解的配置configuration,javasetget也就是在上面说的拼接我们自己产生的java类的简单结构。

private String name;

private String Datatype;

private int keyType;

字段就是在mysql建表时候的每一列

private String tname;

/

key 字段名 value字段类

/

private Map columns;

private ColumnInFo onlyPrivate;

private List priKeys;

这个表呢也就可以记录下整个表了 map中也就是整个表,记录下主键 很好理解这样我们只要有足够多的数据传入我们就可以在java中改了整张表,但是我们必去得做一个query类,用来我把这个数据类传入就可以在数据库中同步更改。

然后大概思路也就成型了,用户可以提供数据库 ,我自动给他生成他表中得类,他调用query中方法,对数据库进行更改。但是怎么通过我生成类对这个映射相联系,然后再映射到数据库呢,我们藏了一个map。

先说一点简单得把tables中获得得数据进行生成java类

这里实现了一个接口,可以处理不同数据库到java得翻译数据类型这里很好懂

public class MysqlTypeConventor implements TypeConvertor{

@Override

public String databaseType2JavaType(String columnType) {

if("varchar".equalsIgnoreCase(columnType)||"char".equalsIgnoreCase(columnType)){

return "String";

}else if("int".equalsIgnoreCase(columnType)

||"tinyint".equalsIgnoreCase(columnType)){

return "Integer";

}else if("double".equalsIgnoreCase(columnType)){

return "double";

}else if("timestamp".equalsIgnoreCase(columnType)){

return "Timestamp";

}

return null;

}

@Override

public String javaType2databaseType(String javaDataType) {

// TODO Auto-generated method stub

return null;

}

}

然后我们把转换器和传进去的字段封装成一个java生成类的工具,就是上面代码提到的哪个工具类

public class JavaFileUtils {

public static JavaFieldGetSet createFieldGetSetSRC(ColumnInFo column,TypeConvertor convertor){

JavaFieldGetSet jfgs= new JavaFieldGetSet();

String javaFieldType = convertor.databaseType2JavaType(column.getDatatype());

jfgs.setFieldInfo("\tprivate "+javaFieldType+" "+column.getName());

StringBuilder getSrc=new StringBuilder();

getSrc.append("\tpublic "+javaFieldType+" get"+StringUTils.firstChar2UpCase(column.getName())+"(){\n");

getSrc.append("\t\treturn "+column.getName()+";\n");

getSrc.append("\t}\n");

jfgs.setGetInfo(getSrc.toString());

StringBuilder setSrc=new StringBuilder();

setSrc.append("\tpublic void set"+StringUTils.firstChar2UpCase(column.getName())+"(");

setSrc.append(javaFieldType+" "+column.getName()+"){\n");

setSrc.append("\t\tthis."+column.getName()+"="+column.getName()+";\n");

setSrc.append("\t}\n");

jfgs.setSetInfo(setSrc.toString());

return jfgs;

}

public static String createJavaSrc(TableInfo tableInfo,TypeConvertor convertor){

Map columns=tableInfo.getColumns();//表装入map

List javaFields=new ArrayList();

for(ColumnInFo c:columns.values()){

javaFields.add(createFieldGetSetSRC(c, convertor));

}

StringBuilder src=new StringBuilder();

src.append("package "+DBManager.getConf().getPoPackage()+";\n\n");

src.append("import java.util.;\n\n");

src.append("import java.sql.;\n\n");

src.append("public class "+StringUTils.firstChar2UpCase(tableInfo.getTname())+"{\n\n");

for(JavaFieldGetSet f:javaFields){

src.append(f.getFieldInfo()+";\n");

}

src.append("\n\n");

for(JavaFieldGetSet f:javaFields){

src.append(f.getSetInfo());

}

src.append("\n");

for(JavaFieldGetSet f:javaFields){

src.append(f.getGetInfo());

}

src.append("}\n");

// System.out.println(src);

return src.toString();

}

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
18天前
|
Java 程序员
JAVA程序员的进阶之路:掌握URL与URLConnection,轻松玩转网络资源!
在Java编程中,网络资源的获取与处理至关重要。本文介绍了如何使用URL与URLConnection高效、准确地获取网络资源。首先,通过`java.net.URL`类定位网络资源;其次,利用`URLConnection`类实现资源的读取与写入。文章还提供了最佳实践,包括异常处理、连接池、超时设置和请求头与响应头的合理配置,帮助Java程序员提升技能,应对复杂网络编程场景。
42 9
|
3月前
|
存储 算法 Java
惊!Java程序员必看:JVM调优揭秘,堆溢出、栈溢出如何巧妙化解?
【8月更文挑战第29天】在Java领域,JVM是代码运行的基础,但需适当调优以发挥最佳性能。本文探讨了JVM中常见的堆溢出和栈溢出问题及其解决方法。堆溢出发生在堆空间不足时,可通过增加堆空间、优化代码及释放对象解决;栈溢出则因递归调用过深或线程过多引起,调整栈大小、优化算法和使用线程池可有效应对。通过合理配置和调优JVM,可确保Java应用稳定高效运行。
140 4
|
3月前
|
Java 程序员
Java数据类型:为什么程序员都爱它?
Java数据类型:为什么程序员都爱它?
52 1
|
3天前
|
SQL 存储 Java
面向 Java 程序员的 SQLite 替代品
SQLite 是轻量级数据库,适用于小微型应用,但其对外部数据源支持较弱、无存储过程等问题影响了开发效率。esProc SPL 是一个纯 Java 开发的免费开源工具,支持标准 JDBC 接口,提供丰富的数据源访问、强大的流程控制和高效的数据处理能力,尤其适合 Java 和安卓开发。SPL 代码简洁易懂,支持热切换,可大幅提高开发效率。
|
15天前
|
SQL Java 程序员
倍增 Java 程序员的开发效率
应用计算困境:Java 作为主流开发语言,在数据处理方面存在复杂度高的问题,而 SQL 虽然简洁但受限于数据库架构。SPL(Structured Process Language)是一种纯 Java 开发的数据处理语言,结合了 Java 的架构灵活性和 SQL 的简洁性。SPL 提供简洁的语法、完善的计算能力、高效的 IDE、大数据支持、与 Java 应用无缝集成以及开放性和热切换特性,能够大幅提升开发效率和性能。
|
21天前
|
IDE Java 程序员
C++ 程序员的 Java 指南
一个 C++ 程序员自己总结的 Java 学习中应该注意的点。
20 5
|
2月前
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(基础篇)
从Java环境的搭建到实际代码的编写,从基本用法的讲解到底层原理的剖析,深度解析Java基础知识。本文是《Java学习路线》专栏的起始文章,旨在提供一套完整的Java学习路线,覆盖Java基础知识、数据库、SSM/SpringBoot等框架、Redis/MQ等中间件、设计模式、架构设计、性能调优、源码解读、核心面试题等全面的知识点,并在未来不断更新和完善,帮助Java从业者在更短的时间内成长为高级开发。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(基础篇)
|
2月前
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
本文是Java基础的进阶篇,对异常、集合、泛型、Java8新特性、I/O流等知识进行深入浅出的介绍,并附有对应的代码示例,重要的地方带有对性能、底层原理、源码的剖析。适合Java初学者。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
|
1月前
|
Java 大数据 程序员
我的程序员之路:自学Java篇
我的程序员之路:自学Java篇
|
1月前
|
Java 数据安全/隐私保护
java学习笔记(基础习题)
java学习笔记(基础习题)
33 0