java mysql sesssion_java操作数据库的几种方式

历史就是一面镜子

回顾自己开发的历程,见证了时代变迁史记,下面我针对java连接数据库的方式说起

0 原生jdbc

先普及下jdbc,怕新入行的人早已沉浸在包装库和框架中,甚至都没用过原生jdbc。

Java数据库连接,全称是Java Database Connectivity,简称JDBC,是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。百科这样解释的Java数据库连接。

开发人员要做的几个步骤:

开发步骤:

1、注册驱动.,告知JVM使用的是哪一个数据库的驱动

2、获得连接.,使用JDBC中的类,完成对MySQL数据库的连接

3、获得语句执行平台,通过连接对象获取对SQL语句的执行者对象

4、执行sql语句,使用执行者对象,向数据库执行SQL语句  获取到数据库的执行后的结果

5、处理结果

6、释放资源.

注意写代码之前,要导入数据库驱动包,连接不同厂商的数据库要用不同的驱动包

1552c5501a227ec4428b82ed367c276b.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

对应的驱动包

70ab72c7081450f7950a745fffa008cb.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

新建项目,普通的java项目就行,导入第三方jar太简单了,自行百度

示例代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

importjava.io.BufferedInputStream;importjava.io.FileInputStream;importjava.io.FileNotFoundException;importjava.io.IOException;importjava.io.InputStream;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;importjava.util.HashMap;importjava.util.Iterator;importjava.util.Properties;importcom.mysql.jdbc.ResultSetMetaData;/***

*@authordgm

* @describe "原生jdbc"

* @date 2020年4月13日*/

public classMysqlTest {//JDBC 驱动名及数据库 URL

static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";static final String DB_URL = "jdbc:mysql://192.168.8.200:3306/bdrackdemo?useUnicode=true&characterEncoding=utf8&autoReconnect=true";//数据库的用户名与密码,需要根据自己的设置

static final String USER = "root";static final String PASS = "cstorfs";static Properties prop = newProperties();//读取数据库配置文件

static voidreadDBSetting(String path) {//Properties prop = new Properties();//读取属性文件mysql.properties

InputStream in = null;try{

in= new BufferedInputStream(newFileInputStream(path));

}catch(FileNotFoundException e) {//TODO Auto-generated catch block

e.printStackTrace();

}try{

prop.load(in);

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}///加载属性列表

Iterator it =prop.stringPropertyNames().iterator();while(it.hasNext()) {

String key=it.next();

System.out.println(key+ "=" +prop.getProperty(key));

}try{

in.close();

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}//return prop;

}public static voidmain(String[] args) {//读取mysql 配置信息

readDBSetting("conf/mysql.properties");

Connection conn= null;

Statement stmt= null;

ResultSet rs= null;try{//注册 JDBC 驱动

Class.forName(prop.getProperty("dbDriver")).newInstance();//打开链接

System.out.println("连接数据库...");

conn=DriverManager

.getConnection("jdbc:mysql://"

+ prop.getProperty("mysqlhost")+ ":"

+ prop.getProperty("mysqlport")+ "/"

+ prop.getProperty("dbname")+ "?useUnicode=true&characterEncoding=utf8&autoReconnect=true",

prop.getProperty("mysqluser"),

prop.getProperty("mysqlpwd"));//执行查询

System.out.println(" 实例化Statement对象...");

stmt=conn.createStatement();

String sql= "SELECT id, username, number FROM student";

rs=stmt.executeQuery(sql);//展开结果集数据库

while(rs.next()) {//输出数据

System.out.print("用户id: " + rs.getInt("id"));

System.out.print(", 用户名: " + rs.getString("username"));

System.out.print(", 学号: " + rs.getString("number"));

System.out.print("\n");

}

}catch(SQLException se) {//处理 JDBC 错误

se.printStackTrace();

}catch(Exception e) {//处理 Class.forName 错误

e.printStackTrace();

}finally{//关闭资源

try{if (rs != null)

rs.close();

}catch(SQLException se3) {

}//什么都不做//关闭资源

try{if (stmt != null)

stmt.close();

}catch(SQLException se2) {

}//什么都不做

try{if (conn != null)

conn.close();

}catch(SQLException se) {

se.printStackTrace();

}

}

}

}

View Code

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

查询结果b961ce234caf527abe683ad7a1eb6aa8.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

恩早期开发就是这么过来,只是自己封装成了JDBC工具,于具体的业务开发人员要写大量的SQL语句,调用时这样的

0bfe563da209a31f8a7734310bd04fa4.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

看上去此种开发模式也很好,只要规模不大,此方式还很好,瓶颈在于数据库连接,现在也不是问题了,社会在进步,池化技术出现了。

池化简单点说就是预先连接好一定数量的连接,等需要时随意从中选择一个进行操作。略了,当时主要用的tomcat自带的池化技术,此时获取数据库连接的代码就变成了这样核心伪代码(tomcat要做些配置):

//构造函数

publicDataAccess(String poolName)

{this.poolName =poolName;this.JNDI = "java:comp/env/" +poolName;

}//获取数据库连接

private void setConnection() throwsException

{

Config config=Config.getConfig();if ( config.getWebserver().equals("tomcat") )

{

Context ctx= newInitialContext();

DataSource ds=(DataSource)ctx.lookup(JNDI);//获取数据库连接

this.conn =ds.getConnection();

}else{//其他server

}

}

1.  hibernate来了

Hibernate是一种ORM框架,全称为 Object_Relative DateBase-Mapping,在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象。

想不明白为啥没有mybatis发展的好,看来拉拢技术人员搞社区还是很重要的。

很遗憾,没有保留以前的老项目,没有自己的电脑,也没有申请github。

//获取加载配置管理类

Configuration configuration = newConfiguration();//不给参数就默认加载hibernate.cfg.xml文件,

configuration.configure();//创建Session工厂对象

SessionFactory factory =configuration.buildSessionFactory();//得到Session对象

Session session =factory.openSession();//使用Hibernate操作数据库,都要开启事务,得到事务对象

Transaction transaction =session.getTransaction();//开启事务

transaction.begin();//把对象添加到数据库中//session.save(user);//数据库操作略//提交事务

transaction.commit();//关闭Session

session.close();

2. mybatis也来了,来的更猛

用的时间稍微长久些,没办法,谁让它势头发展的好,也有大厂强烈支持。

重点也是关注架构、缓存和事务

简单demo如下:

packagespring.daopublic interfaceMybatisDao {

ListselectUser();

}public class MybatisDaoImpl implementsMybatisDao {publicSqlSession sqlSession;publicMybatisDaoImpl(SqlSession sqlSession) {this.sqlSession =sqlSession;

}

@Overridepublic ListselectUser() {//TODO Auto-generated method stub

return this.sqlSession.selectList("spring.dao.MybatisDao.selectUser");

}

}//测试代码

public classMybatisTest {public static voidmain(String[] args) {//TODO Auto-generated method stub

try{

System.out.println("开始mybatis实验");

MybatisDao userDao;

SqlSession sqlSession;

String resource= "conf/mybatis-config.xml";

InputStream inputStream=Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory= newSqlSessionFactoryBuilder()

.build(inputStream);

sqlSession=sqlSessionFactory.openSession();

userDao= newMybatisDaoImpl(sqlSession);

List userList =userDao.selectUser();for(HashMap user : userList) {

System.out.println(user);

}

sqlSession.close();

System.out.println("结束mybatis实验");

}catch(IOException e) {

e.printStackTrace();

}catch(Exception e) {

e.printStackTrace();

}

}

}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

配置文件三个如下

mybatis-config.xml

/p>

PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-config.dtd">

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

myBatisMapper.xml文件内容

/p>

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

SELECT id, username, number FROM student

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

数据库配置mysql.properties

#MySQL for mybatis

mybatis.driver=com.mysql.jdbc.Driver

mybatis.url=jdbc:mysql://192.168.8.200:3306/bdrackdemo?useUnicode=true&characterEncoding=utf8&autoReconnect=true

mybatis.username=root

mybatis.password=cstorfs

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

执行测试代码效果:

c4fb62f414cd88b52828de686d4fa4dd.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

注意配置型的文件不能放错位置,要么就改加载属性文件的代码,记得导入数据库驱动包和mybatis.jar

缓存分两种,一级缓存和二级缓存。

一级缓存

一级缓存 Mybatis的一级缓存是指SQLSession,一级缓存的作用域是SQlSession, Mabits默认开启一级缓存。 在同一个SqlSession中,执行相同的SQL查询时;第一次会去查询数据库,并写在缓存中,第二次会直接从缓存中取。 当执行SQL时候两次查询中间发生了增删改的操作,则SQLSession的缓存会被清空。 每次查询会先去缓存中找,如果找不到,再去数据库查询,然后把结果写到缓存中。 Mybatis的内部缓存使用一个HashMap,

public class PerpetualCache implementsCache {private finalString id;//是个map对象

private final Map cache = new HashMap<>();publicPerpetualCache(String id) {this.id =id;

}

@OverridepublicString getId() {returnid;

}

@Overridepublic intgetSize() {returncache.size();

}

@Overridepublic voidputObject(Object key, Object value) {

cache.put(key, value);

}

}

key为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。 SqlSession执行insert、update、delete等操作commit后会清空该SQLSession缓存。

几种情况:

第一种情况:同个session进行两次相同查询

3bc41838bef7e514fda1f005416d6f1d.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

结论:MyBatis只进行1次数据库查询。

第二种情况:同个session进行两次不同的查询

627fd935c53e93da0df03d366d789ecd.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

结论:MyBatis进行两次数据库查询。

第三种:不同session,进行相同查询。

58b4c3cf6bcfcad8a7739e8532e037a9.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

结论:MyBatis进行两次数据库查询。

第四种情况:同个session,查询之后更新数据,再次查询相同的语句

直接下结论了:更新操作之后缓存会被清除

小结:一级缓存是SqlSession级别的缓存,Mybatis默认是开启一级缓存的,当调用SqlSession的修改、添加、删除、commit()、close()等方法时,就会清空一级缓存。

二级缓存

之所以称之为“二级缓存”,是相对于“一级缓存”而言的。既然有了一级缓存,那么为什么要提供二级缓存呢?我们知道,在一级缓存中,不同session进行相同SQL查询的时候,是查询两次数据库的。显然这是一种浪费,既然SQL查询相同,就没有必要再次查库了,直接利用缓存数据即可,这种思想就是MyBatis二级缓存的初衷。

另外,Spring和MyBatis整合时,每次查询之后都要进行关闭sqlsession,关闭之后数据被清空。所以MyBatis和Spring整合之后,一级缓存是没有意义的。如果开启二级缓存,关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到mapper namespace的二级缓存中。这样,缓存在sqlsession关闭之后依然存在。

默认情况下,MyBatis只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存,见:MyBatis一级缓存介绍。要启用全局的二级缓存,只需要在SQL映射文件中添加一行:

二级缓存是Mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

上面这个简单语句的效果如下:

映射语句文件中的所有 select 语句的结果将会被缓存。

映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。

缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。

缓存不会定时进行刷新(也就是说,没有刷新间隔)。

缓存会保存列表或对象的1024个引用。

缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

这些属性可以通过 cache 元素的属性来修改。比如:

eviction="FIFO"

flushInterval="60000"

size="512"

readOnly="true"/>

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

可用的清除策略有:

LRU – 最近最少使用:移除最长时间不被使用的对象。

FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。

WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

默认的清除策略是 LRU。

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

提示:二级缓存是事务性的。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。

小结: 二级缓存是mapper映射级别的缓存,默认是不开启的,多个SqlSession去操作同一个Mapper映射的sql语句是共用二级缓存的,二级缓存是跨SqlSession的。

框架前几部分都是属性文件解析,构造工厂,生产产品做真正的事

记一次使用mybatis使用出现的排序问题: ${}和 #{}的区别

由于开始时排序字段,特别是分页查询时,传的参数有第几页,每页几条记录,排序字段,是动态设置的,有时从前端传来,按某些个字段排序

/*** 学生查询考试任务列表

*@paramuser

*@parampageSize

*@parampageNumber

*@paramstatus,试卷状态(0-N, 1. 未发布,可编辑修改和删除, 2. 已发布,可查看和停用, 3. 已结束,可审阅, 默认为0代表所有状态)

*@paramname, 试卷名字模糊查询

*@paramsortOrder, 排序字段 *@return

*/@SuppressWarnings({"rawtypes", "unchecked"})

@RequestMapping(value= "/list", method = RequestMethod.GET, produces = "application/json; charset=utf-8")

@LoginRequired

@CrossOriginpublicJSONObject list(@CurrentUser User user,

@RequestParam(value= "pageSize", required = false, defaultValue = "10")Integer pageSize,

@RequestParam(value= "pageNumber", required = false, defaultValue = "1")Integer pageNumber,

Integer status,

@RequestParam(value= "name", required = false, defaultValue = "") String name,

@RequestParam(value= "sortOrder", required = false, defaultValue = " cp.id desc ") String sortOrder)

就是这个sortOrder

52ed9f48c601d22972a7167417bc18cc.pngwAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

大致就这样了,每个人都可以接着扩展开发。框架性迭代总是这样,xml到json,sql写在xml文件里到如今通过注解实现(spring也是如此,早期都是xml大量配置,如今也转换到注解配置),框架越来越包装了,愿每个码农都把基础学好,再学框架,不要一上来就mybatis,据说新码农都没写过原生servlet,更别提开发了。。。

总结:

自己早年封装的jdbc组件,简单易用,适合小规模化开发,主要当时技术受限,大量数据库连接没处理好,没有池化和缓存策略,且对码农的sql功底很强,其实面向SQL编程

hibernate,个人觉得一个很不错得到orm框架,脱离了部分sql,只是没推广好

mybatis ,从架构上来说和hibernate雷同,生态圈建立的好,也有大厂光环。

汇总一句话:再好的orm,也脱离不了最最最基本的JDBC,劝扎进框架圈里的人,务必打好基础,框架各有千秋,没有最好,只要合适!!!

参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值