Вы должны изучить механизм Spring ORM

база данных Spring Hibernate ORM
Вы должны изучить механизм Spring ORM

Редактор вчера весь день работал над кодом проекта, но после целого дня работы я обнаружил, что застрял на операции с базой данных.Я подумал об этом некоторое время и обнаружил, что проект должен использовать Spring orm для интеграции hibernate для работы с базой данных. , но я не буду! Я и раньше изучал интеграцию SSH, но ценные знания были возвращены учителю! Я тоже очень беспомощен. В порядке! Если нет, то научись! Вот так!

Во-первых, общая структура фреймворка Spring ORM.

Когда дело доходит до ORM, это так называемое объектно-реляционное сопоставление, которое можно просто понимать как модель, которая сопоставляет объекты в java с таблицами в базе данных. Так что же такое Spring ORM? Давайте посмотрим на структуру исходного кода Spring ORM, чтобы узнать! Выкладываю картинку ниже:

Как видно из рисунка, в модуле Spring ORM по умолчанию поддерживаются две технологии, а именно hibernate5 и jpa. . Для получения дополнительной информации об этих двух технологиях перейдите в Google!

Прежде чем читать второй раздел ниже, я хотел бы рассказать о том, как мы вообще работаем с базой данных с моего понимания, чтобы мы могли принципиально понять принцип работы и не быть обманутыми различными классами в Spring ORM. !

Общая процедура работы с базой данных состоит из следующих шагов:

  • 1. Настройте источник базы данных(DataSource), Это легко понять. Поскольку вы хотите работать с базой данных, откуда берутся ваши данные? Это должна быть база данных!
  • 2. Установите связь с базой данных(Connection), очень легко понять, если вы хотите поговорить с редактором по телефону, у вас должна быть ссылка на ваш инструмент! Правильно, это телефонная линия!
  • 3. Получить сеанс(Session),разговор это звонок между вами и редактором.После звонка ссылка выше может быть закрыта или нет,зависит от вашего настроения! Ха-ха!
  • 4, а затем работать с базой данных!

Во-вторых, подробно расскажите о важных классах Spring ORM и их использовании.

Давайте расширим спящий режим в исходном коде Spring ORM, как показано ниже:

В исходном коде мы сосредоточимся на нескольких важных классах и интерфейсах, а именно:

  • HibernateOperationsИнтерфейс, который инкапсулирует многие операции на основе hibernate API, который используетсяHibernateTemplateРеализация, хотя этот интерфейс используется не очень часто, его можно использовать для тестирования в Spring.
  • HibernateTemplateкласс, реализующийHibernateOperationsИнтерфейс, поэтому этот класс также имеет множество операций с базой данных, основанных на спящем режиме. Но внимательные друзья обнаружат, что в его названии фигурирует шаблон шаблона. Можно предположить, что это класс шаблона. Да, этот класс является воплощением шаблона проектирования метода шаблона. Шаблон проектирования метода шаблона вы можете найти в моя предыдущая статья.пост в блогеРасскажите о моем понимании шаблона проектирования «метод шаблона» (Шаблон), Этот класс предоставляет метод шаблона следующим образом:
@Override
@Nullable
public <T> T execute(HibernateCallback<T> action) throws DataAccessException {
	return doExecute(action, false);
}

Этот метод шаблона является суперпростым, переданным в экземпляр Hibernate обратного вызова, а затем выполнитьdoExecute()метод. Вы спросите, а как насчет этогоHibernateCallbackчто это?doExecute()Что это? ОткрытымHibernateCallbackИсходный код:

@FunctionalInterface
public interface HibernateCallback<T> {
	@Nullable
	T doInHibernate(Session session) throws HibernateException;
}

Ничего себе, это слишком просто, тогда я бы подумал, раз это интерфейс, то должен быть класс реализации! Потом искал, искал и не нашел. Наконец выяснилось, что интерфейс изначально@FunctionalInterfaceОформление — это функциональный интерфейс, поэтому мы можем использовать его с выражениями Lamada! Что касается параметров, объявленных в интерфейсеSessionиdoInHibernate()метод, на самом деле причина очень проста, то есть путем получения экземпляра сеанса(还记得你和小编的一次通电话吗!上面第一节第三步)сделать что-то с базой данных(上面第四步), эти операции(比如数据持久化)ты сможешьdoInHibernate()Напишите это в методе! детали следующим образом:

new HibernateTemplate().execute((e) -> e.createQuery("select * from user"));

Конечно, в реальном использовании мы не можем просто сделать это напрямую.new HibernateTemplate(), вы также должны пройти вsessionFactoryпример, а общее инстанцирование делается контейнером Spring, нет необходимости выводить new, здесь просто каштан, акцент делается на демонстрациюHibernateCallbackкак пользоваться. Или, поскольку это функциональный интерфейс, он не обязательно зависит отHibernateTemplateкласс, пока вы проходите вSessionПросто пример!

Далее давайте посмотримdoExecute()метод:

@SuppressWarnings("deprecation")
@Nullable
protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNativeSession) throws DataAccessException {
	Assert.notNull(action, "Callback object must not be null");//先断言保证action不为空
	Session session = null;//会话对象
	boolean isNew = false;//是不是新的会话
	try {
		session = obtainSessionFactory().getCurrentSession();//初始化会话对象
	}
	catch (HibernateException ex) {
		logger.debug("Could not retrieve pre-bound Hibernate session", ex);
	}
	if (session == null) {
		session = obtainSessionFactory().openSession();
		session.setFlushMode(FlushMode.MANUAL);//设置提交方式
		isNew = true;
	}
	try {
		enableFilters(session);
		//根据是否强制将原生Hibernate会话session暴露给回调代码,默认为false,如果是true,就做一个代理
		Session sessionToExpose =
				(enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));
		return action.doInHibernate(sessionToExpose);
	}
	catch (HibernateException ex) {
		throw SessionFactoryUtils.convertHibernateAccessException(ex);
	}
	catch (PersistenceException ex) {
		if (ex.getCause() instanceof HibernateException) {
			throw SessionFactoryUtils.convertHibernateAccessException((HibernateException) ex.getCause());
		}
		throw ex;
	}
	catch (RuntimeException ex) {
		// Callback code threw application exception...
		throw ex;
	}
	finally {
		if (isNew) {
			SessionFactoryUtils.closeSession(session);
		}
		else {
			disableFilters(session);
		}
	}
}
  • LocalSessionFactoryBeanкласс, который представляет собойFactoryBeanобъект, используемый для создания всехSession, обычно мы настраиваем bean-компонент в файле конфигурации Spring

3. Подойди к каштану, чтобы подавить шок!

数据库结构:

工程结构:

Student.java

package wokao666.pojo;

import java.io.Serializable;

public class Student implements Serializable {//序列化

	private int id;
    private String name;
	private String mobile;
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", mobile=" + mobile + "]";
	}
	public Student(int id, String name, String mobile) {
		super();
		this.id = id;
		this.name = name;
		this.mobile = mobile;
	}
	public Student() {
		super();
	}
	public Student(String name, String mobile) {
		super();
		this.name = name;
		this.mobile = mobile;
	}
	这里省略一大堆get/set方法
}

SpringORMTest.java

package wokao666.test;

import java.util.Arrays;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate5.HibernateTemplate;
import wokao666.pojo.Student;

public class SpringORMTest {
	public static void saveStudent(ApplicationContext context) {
		HibernateTemplate template = (HibernateTemplate) context.getBean("hibernateTemplate");
		//默认为只读模式,要设置改为允许delete、save、update等操作
		template.setCheckWriteOperations(false);//注意此处一定要设置关闭,因为HibernateTemplate默认会对Session进行检查
		Student stu = new Student("0", "000000000000000");
		template.save(stu);
		System.out.println(Arrays.toString(template.find("from Student", null).toArray()).toString());
	}
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		saveStudent(context);
	}
}

applicationContext.xml

<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/jdbc
         http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
         http://www.springframework.org/schema/tx 
         http://www.springframework.org/schema/tx/spring-tx.xsd
         http://www.springframework.org/schema/aop 
         http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!-- 加载属性文件 -->
	<context:property-placeholder
		ignore-unresolvable="true" location="classpath*:datasource.properties" />
	<!-- 配置数据源 -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${spring.datasource.driverClassName}" />
		<property name="url" value="${spring.datasource.url}" />
		<property name="username" value="${spring.datasource.username}" />
		<property name="password" value="${spring.datasource.password}" />
	</bean>
	<!-- 配置session工厂 -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>./student.hbm.xml</value>
			</list>
		</property>
	</bean>
	<!-- 最后配置 HibernateTemplate bean-->
	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
</beans>

datasource.properties

spring.datasource.url = jdbc:mysql://localhost:3306/demo_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName = com.mysql.jdbc.Driver  

student.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="wokao666.pojo.Student" table="user">
		<id name="id" type="java.lang.Integer">
			<column name="Id" />
			<generator class="identity" />
		</id>
		<property name="mobile" type="java.lang.String" column="MOBILE"
			length="100" />
		<property name="name" type="java.lang.String" column="NAME"
			length="100" />
	</class>
</hibernate-mapping>

build.gradle

apply plugin: 'java'

repositories {
    jcenter()
}

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.21'
    testCompile 'junit:junit:4.12'
    compile 'org.springframework:spring-context:5.0.4.RELEASE'
    compile 'org.springframework:spring-orm:5.0.4.RELEASE'
	compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.4'
	compile group: 'org.hibernate', name: 'hibernate-core', version: '5.2.9.Final'
	compile group: 'cglib', name: 'cglib', version: '3.2.4'
	compile group: 'org.springframework', name: 'spring-tx', version: '5.0.0.RELEASE'
	compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.8.8'
}

4. Обзор других функций(具体可以自行阅读源代码)

  • 1,HibernateTemplateУправляйте делами сами, нам не нужно управлять делами, не нужно, чтобы мы открывалиSession, закрытиеSession

  • 2. ВHibernateTemplate, в него так же можно инжектить фильтры, все фильтры будут открываться перед выполнением операции, и полностью закрываться после завершения операции

  • 3. Если установленоexposeNativeSessionзаtrue, затемsessionПрокси будет возвращен при подавленииcloseВызывается метод, и одновременно включаются такие функции, как кэширование запросов и тайм-аут транзакции!

  • 4. По умолчаниюHibernateTemplateДля транзакции только для чтения, если мы хотим записать в нее, мы должны ее отменить.sessionПроверить механизм, позвонитьsetCheckWriteOperationметод

  • 5. Вы также можете установить кеш запросов и указать область кеша запросов