关于hibernate的一些简单介绍

最近疫情严重,公司无限延长开工时间,心情也跟着变得沉重。先祝愿武汉早日渡过难关,加油武汉,加油中国!

过年回家,想了想关于自己未来的目标规划,发现自己陷入了死胡同,本来计划一直更新的博客也停止了更新,姐姐劝我博客可以继续写,对自己有好处。所以,在2020/2/10一点,继续更新我的博客。

背景:当前市场上,由于各种项目都比较大,可用性和优化要求都较高,于是持久层框架大家都更偏向于Mybatis而忽略了曾经也风靡一时hibernate。让我感受最深的今天群里一个做了8年开发的前辈,在我们讨论H和M差别时,他说了一句“Hibernate这么垃圾的框架还有人用么?还有你们说的hql是什么鬼?”所以我觉得很多人其实并不了解它,甚至觉得学它毫无用处。确实,能熟练使用mybatis也能完成各种项目,也是市场最流行的,但是个人建议,每个框架存在都有它优点,愿意了解下的就继续看看,当然,本人技术有限,欢迎各位批评和指导。

1:hibernate介绍

1.1,hibernate是什么:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的JaveEE架构中取代CMP,完成数据持久化的重任。(此处引用百度百科的说明)

1.2,hibernate能做什么:上一段话已经大致介绍了,hibernate是一个持久层ORM框架,它可以帮我们做数据库的CRUD,当我们做了对象关系的映射,我们就可以通过操作对象的方式来操作数据库。完全不用自己再来写sql语句,这对不喜欢写sql的人来说是一个福音把。

1.3,和mybatis的差别:在我自己理解,M和H都是ORM框架,而差别在于H的映射做的更加完整而且联合JPA使用映射更加简单,也让人更好理解,而M需要自己通过sql语句和xml文件或者annotation使用,sql语句直接操作的还是表和字段,并不是对象。那么为啥更多人倾向于M呢?还是因为H的映射,现在大多项目都较为庞大,而Hibernate的映射让他在大型项目中显得过于笨重,占用的资源过高,拖累了项目的运行速度。

1.4,hibernate该在什么地方使用:在我自己感觉中,H和M在什么地方都可以使用,如果真要纠结,那么在中小型项目,特别是管理系统之类的使用,更让程序员更加感到善意。

2:hibernate具体使用

2.1,hibernate使用需要些什么;以下是我自己去年做一个管理系统时的ssh全部配置文件,可以copy简单修改就能使用。

pom依赖:

<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<slf4j-version>1.7.25</slf4j-version>
		<spring.version>5.0.4.RELEASE</spring.version>
		<hibernate.version>5.2.10.Final</hibernate.version>
		<aspectj.version>1.8.12</aspectj.version>
	</properties>

	<dependencies>
		<!-- Aspectj -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>${aspectj.version}</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${aspectj.version}</version>
		</dependency>
		<!-- spring整合Aspectj -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>${spring.version}</version>
		</dependency>
		
		<!-- spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- springMVC -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- springTest -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- json解析 -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.5</version>
		</dependency>
		<!-- self4j日志 -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-jdk14</artifactId>
			<version>${slf4j-version}</version>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${hibernate.version}</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-ehcache</artifactId>
			<version>${hibernate.version}</version>
		</dependency>
		<!-- 二级缓存ehcache -->
		<dependency>
			<groupId>net.sf.ehcache</groupId>
			<artifactId>ehcache</artifactId>
			<version>2.10.4</version>
		</dependency>
		<!-- spring整合JPA -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>2.0.1.RELEASE</version>
		</dependency>
		<!-- hibernate end -->
		<!-- c3p0数据源 -->
		<dependency>
			<groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.5.2</version>
		</dependency>
		<!-- mysql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.4</version>
		</dependency>
		<!-- servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
			<scope>provided</scope>
		</dependency>
		<!-- log4j -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<!-- junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
		<!-- cglib -->
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>3.2.5</version>
		</dependency>
	</dependencies>
	<!-- java1.8插件 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>

ssh的applicationContext.xml核心配置:包名等等自己按照项目名称做简单修改,我着只是示列。


```yaml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.1.xsd">
	<!-- 1.注解扫描包,加载bean -->
	<context:component-scan base-package="com.dream">
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	</context:component-scan>
	<!-- 2.加载属性文件 -->
	<bean id="annotationPropertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:init.properties</value>
			</list>
		</property>
	</bean>
	<!-- 3.配置数据源:jdbc+pool -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<property name="driverClass" value="${jdbc.driver}" />
		<property name="jdbcUrl" value="${jdbc.url}" />
		<property name="user" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<!-- 请求超时时间 -->
		<property name="checkoutTimeout" value="30000" />
		<!--60秒检查所有连接池中的空闲连接。默认值: 0,不检查 -->
		<property name="idleConnectionTestPeriod" value="30" />
		<!-- 连接数据库连接池最大空闲时间 -->
		<property name="maxIdleTime" value="30" />
		<!-- 连接池初始化连接数 -->
		<property name="initialPoolSize" value="5" />
		<property name="minPoolSize" value="5" />
		<property name="maxPoolSize" value="20" />
		<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 -->
		<property name="acquireIncrement" value="5" />
	</bean>
	<!-- 4.配置hibernate的SessionFactory -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<!-- 注入数据源 相关信息看源码 -->
		<property name="dataSource" ref="dataSource" />
		<!-- hibernate配置信息 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
				<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
				<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
				<!-- 开启二级缓存 ehcache -->
				<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
				<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
				<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
				<prop key="hibernate.cache.provider_configuration_file_resource_path">${hibernate.cache.provider_configuration_file_resource_path}
				</prop>
			</props>
		</property>
		<!-- 扫描hibernate注解配置的entity 
		<property name="packagesToScan" value="com.qf.wobb.model" />-->
		<property name="packagesToScan">  
            <list>
                <value>com.dream.ssh.po</value>
            </list>
        </property>
	</bean>
	<!-- 5.配置事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate5.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

init.properties数据库参数:

#mysqldatabasesetting
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/myssh?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

#hibernateconfig
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true
hibernate.format_sql=false
hibernate.hbm2ddl.auto=update
hibernate.cache.use_second_level_cache=false
hibernate.cache.use_query_cache=false
hibernate.current_session_context_class=thread
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate.cache.provider_configuration_file_resource_path=ehcache.xml

log4j.properties:log4j打印配置

###setloglevels###INFO
log4j.rootLogger=INFO,stdout,E

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE}%5p %c{1}:%L-%m%n
log4j.logger.org.quartz=INFO
log4j.appender.E=org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File=logs/mylogs.log
log4j.appender.E.DatePattern=yyyy-MM-dd'.log'
log4j.appender.E.Threshold=INFO
log4j.appender.E.layout=org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern=%-d{yyyy-MM-ddHH\:mm\:ss}[%c][%t\:%r]-[%p]%m%n

springMVC配置文件:

<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-4.1.xsd
            http://www.springframework.org/schema/aop
        	http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">

<!-- 1.启动mvc注解 -->
	<mvc:annotation-driven conversion-service="conversionService" />
	<!--配置ConversionService -->
	<bean id="conversionService"
		class="org.springframework.context.support.ConversionServiceFactoryBean">
		<property name="converters">
			<set>
				<ref bean="dateConverter" />
			</set>
		</property>
	</bean>

	<!-- 2.扫描controller -->
	<context:component-scan base-package="com.dream.ssh.controller" />

	<!-- 3.不拦截静态资源 -->
	<mvc:resources mapping="/sb-admin2/**" location="/sb-admin2/"></mvc:resources>

	<!-- 4.视图解析器 -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- jsp所在的位置 -->
		<property name="prefix" value="/WEB-INF/jsp/" />
		<!-- jsp文件的后缀名 -->
		<property name="suffix" value=".jsp" />
	</bean>
	
	<!-- 统一异常处理 -->
	<aop:config>
		<aop:advisor advice-ref="aopExceptionHandler" pointcut="execution(* com.dream.ssh.controller..*.*(..))"/>
	</aop:config>
</beans>

以上配置文件需要自己针对项目名称,包名等等做做简单修改即可使用。好,接着谈hibernate的使用。

2.2,hibernate具体使用:
hibernate使用核心是session,此处的session和HttpSession不是同一session,你可以把它看成对数据库的一次通信,经过以上配置与spring集成后只需要在dao层使用@Resource或者@Autowired 注解就可以注入SessionFactory

@Resource  //@Autowired 
	private SessionFactory sessionFaction;
    Session session = sessionFaction.getCurrentSession();

这样就可以得到与当前线程绑定的session。

2.3,hibernate的几种常见查询方式:

既然拿到了session,就可以具体操作了,hibernate常见几种查询方式有:
2.3.1:自带的crud方法:
session.get()//获取
session.load()//获取
session.update()//修改
session.save()//添加,保存
session.delete()//删除
简单对单一对象操作可使用

2.3.2:QBC查询
session.createCriteria()//不常用,自己试验下就好。

2.3.3:本地sql查询:
session.createNativeQuery(sqlString);//自己写sql语句进行查询,用此方法还不如用Mybatis。

2.3.4:hql查询:个人推荐,hql也就是hibernate query language,hibernate的查询语句;此查询语句和sql有何不同呢?sql是针对的是表,字段,而hql针对的是对象,属性,我们只需要对对象进行操作,hibernate就可以自动生成sql语句进行查询;下面是一些实际操作的例子。

我们拿user来做示范:使用jpa注解快速建表和做映射;
@Entity
@Table(name = "t_user")
public class User {
	private final static Logger LOG = LogManager.getLogger(User.class);

```java
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@Column(length = 26, unique = true, nullable = false)
private String loginName;

@Column(length = 50, nullable = false)
private String password;

@Column(length = 26)
private String name;

@Temporal(TemporalType.TIMESTAMP)
private Date createTime;

@ManyToMany
@JoinTable(name = "t_user_role" , joinColumns = @JoinColumn(name = "user_id") ,
inverseJoinColumns = @JoinColumn(name = "role_id"))
private List<Role> roles = new ArrayList<Role>();

public List<Role> getRoles() {
	return roles;
}

public void setRoles(List<Role> roles) {
	this.roles = roles;
}

public Date getCreateTime() {
	return createTime;
}

public void setCreateTime(Date createTime) {
	this.createTime = createTime;
}

public Integer getId() {
	return id;
}

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

public String getLoginName() {
	return loginName;
}

public void setLoginName(String loginName) {
	this.loginName = loginName;
}

public String getPassword() {
	return password;
}

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

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

public User() {
	super();
	// TODO Auto-generated constructor stub
}

@Entity //申明实体类
@Table(name = “user”) //数据库中user表,name:表名

@Id //申明主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //主键产生的方式,GenerationType.IDENTITY为mysql默认,其他数据库可选。

@Column(length = 26, unique = true, nullable = false) //设置属性对应字段的参数,可选name字段名,length长度,unique是否唯一,nullable是否为空等等。

@Temporal(TemporalType.TIMESTAMP) //此处为前端时间格式化,与hibernate无关。

@ManyToMany
@JoinTable(name = “t_user_role” , joinColumns = @JoinColumn(name = “user_id”) ,
inverseJoinColumns = @JoinColumn(name = “role_id”))//多对多维护关系数据一方的配置,另一方为:
@ManyToMany(mappedBy = “users”)

使用了这些annotation,就可以运行下项目,hibernate会自动建表,然后我们就可以愉快的CRUD了:
比如:sessionFactory.getCurrentSession().save(uPo);使用save插入一个user
或者:User user = findById(id);
sessionFactory.getCurrentSession().delete(user);删除一个user,此处删除的入参是对象,所以先查询了下此对象。

接着就是等待已久hql查询了:
test01:通过登录名查询user

@Resource
	private SessionFactory sessionFactory;
	@Override
	//通过登录名查询user
	public User findByLoginName(String username) {
		String hql = "from User u where u.loginName = :loginName";
		Query<User> query = sessionFactory.getCurrentSession().createQuery(hql, User.class);
		User user = query.setParameter("loginName", username).uniqueResult();
		return user;
	}

test02:查询所有user

	@Override
	public List<User> findAll() {
		//查询所有user
		String hql = "from User";
		List<User> list = sessionFactory.getCurrentSession().createQuery(hql, User.class).list();
		return list;
	}

test03:模糊匹配并做分页与排序,start分页起始参数,length返回数据最大个数,search模糊匹配值,dir排序参数,asc – 升序desc – 降序

@Override
	public List<User> findAllByPage(Integer start, Integer length, String search,String dir) {
		LOG.info(dir);
		String hql = "from User u where u.name like :name or u.loginName like :name order by u.loginName " + dir;
		List<User> list = sessionFactory.getCurrentSession().createQuery(hql, User.class).setParameter("name", "%" + search + "%").setFirstResult(start).setMaxResults(length).list();
		return list;
	}

看了上面几个例子,是不是觉得更直观的感受到hibernate操作对象的方式去操作表和字段?什么,还么有?那么我们再来看看hql和sql的差别;

hql:
from User u where u.name like '%001%' or u.loginName like '%001%' order by u.loginName asc  
相同的sqlselect * from t_user u where u.name like '%001%' or u.loginName like '%001%' order by u.loginName asc 

hql查询省略了select *,且User与sql中t_user不同,hql中User为对象User,而sql中的t_user为表,hql中的name,loginname等都为user对象的属性,而sql中的name和loginname等都为表的字段,所以hibernate是通过操作对象的方式对表进行操作,而具体的sql语句由hibernate底层通过我们的对象关系映射去书写并且发送,获取的返回的值也是一个user对象的集合,我们需要关心的只有对象和属性,而且我们再查询出user后只需要getRoles()就可以得到关联的角色。再对比mybatis中的sql语句:

select u.*, 
		r.id as r_id,
		r.name as r_name,
		r.description as r_description
		from t_user u left join t_user_role ur on (u.id = ur.user_id) 
		left join t_role r on (ur.role_id = r.id)
		where u.id = #{id}

可以发现省去了许多写sql的过程。

2.4,hibernate的一些常用知识点:

2.4.1:一级缓存和二级缓存:hibernate一级缓存就是session级别的缓存,当session关闭时,缓存清空。二级缓存就是session factory级别的缓存,缓存数据存放在session factory中,需要做配置,上面核心配置中有注释开启二级缓存。
2.4.2:惰性加载,hibernate默认为懒加载,即不用不查询,使用时再进行一次查询,可在xml文件或者@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)中设置为迫切加载fetch = FetchType.EAGER
2.4.3:级联,级联也就是对当前对象进行CRUD时是否对关系数据同步进行修改。此处:cascade = CascadeType.ALL就是设置所有操作同步,可单独设置修改同步删除同步等等。

当然还有事务,已经在配置文件中配置了,service层一个注解@Transactional就搞定了。主要可以关注的就是hql查询把,也是hibernate使用最多的查询方式,hql与sql区别不大,把表换成对象,字段换成属性就ok了。hibernate作为当前不太流行的框架,各有各的选择把,有喜欢用的可以了解一下,不喜欢的mybatis也够用了,半夜写博客,总感觉困困的,很多东西没写出来,也有很多东西写的不明确不好,欢迎指出,欢迎批评,欢迎交流,后边会跟着写写一些常用框架,比如Mybatis,spring,springMVC,shiro,springboot,dubbo,springcloud等等。一起学习知识,一起分享知识。

最后,祝愿武汉,祝愿祖国!!!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值