SSH整合JPA+Mysql

SSH整合JPA+Mysql

一、什么是JPA:

(1)JPA(Java Persistence API)即Java持久化规范,他为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关心数据,目的是结束现在Hibernate、TopLink、JDO等ORM框架各自为营的局面。JPA是在充分吸收了现有的Hibernate、TopLink、JDO等ORM框架的基础上发展而来的,具有易于使用、伸缩性强等优点。

(2)JPA的总体思想和现有Hibernate、TopLink、JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:

ORM映射元数据:

JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;

②API:

用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。

③查询语言:

这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。

(3)提示:JPA不是一种新的ORM框架,他的出现只是用于规范现有的ORM技术,他不能取代现有的Hibernate、TopLink等ORM框架。相反,在采用JPA开发是,我们仍将使用到这些ORM框架,只是此时开发出来的应用不再依赖与某个持久爱化框架提供商。应用可以在不修改代码的情况下在任何JPA环境下运行,做到真正低耦合,可扩展的程序设计。

 

二、基于Hibernate实现JPA的简单程序:

1、导入所需要的pom.xml文件依赖:

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

2、创建并编写persistence.xml文件,名称和路径都是固定的,位于类路径的META-INF目录下,如果是maven工程,则是在src/main/resources/METE-INF路径下。

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">  
  
<!-- Name属性用于定义持久化单元的名字 (name必选,空值也合法); -->
<!-- transaction-type 指定事务类型(可选):本地RESOURCE_LOCAL;和全局JTA,一般用本地就可以了 -->
<persistence-unit name="jpatest" transaction-type="RESOURCE_LOCAL">  
   <!-- <provider>org.hibernate.ejb.HibernatePersistence</provider> -->
   <properties>    
	   	<!-- 连接数据库 -->
	    <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />  	
 	    <property name="hibernate.connection.url" 
	   				value="jdbc:mysql://localhost:3306/jpatestdatabase?useUnicode=true&amp;characterEncoding=UTF-8" />
	    <property name="hibernate.connection.username" value="root" />  
	    <property name="hibernate.connection.password" value="admin" />  
	    
	    <!-- 设置数据库方言 -->
	    <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />  
	    <property name="hibernate.max_fetch_depth" value="3" />  
	    <property name="hibernate.hbm2ddl.auto" value="update"/>  
	    <property name="hibernate.show_sql" value="true" />  
	    <property name="hibernate.format_sql" value="true" />
        <property name="hibernate.jdbc.fetch_size" value="18" />
   		<property name="hibernate.jdbc.batch_size" value="10" />
   </properties>  
</persistence-unit>
</persistence>

persistence-uni标签的name属性:持久化单元的名字,这个属性必须要有,用来后面的EntityManagerFactory生成实例的名字。 

transaction-type:使用的实物类型,默认是RESOURCE_LOCAL事务,还有一个是JTA事务。

provide:EJB Persistence provide 的一个实现类,可以分为不同的ORM,例如MyBatis和Hibernate。

properties:配置数据库厂商的属性,比如SQL-server和mysql、Oracle等。

3、创建实体类:(可以使用标签设置实体类属性)

package com.zwp.bean;
//注解标签都是是位于javax的包。
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

/*
@Table(name="p_table")指定数据库表名,我所导入的jar存在冲突,会抛出异常,
可以直接使用@Entity(name="p_table")来指定表名就可以解决这个问题了,
但是如果使用这种方式修改表名,就不能创建Query对象,会抛出异常。
 */
//指定需要映射的类
@Entity
public class Person {
	
	public Person() {
	}
	public Person(String name) {
		this.name = name;
	}
	
	private Integer id;//主键
	private String name;
	private Date birthday;//时间类型
	private Gender gender=Gender.MAN;//枚举类型,设置默认值是MAN
	private String info;//大文本类型
	private Byte[] file;//二进制类型
	private String imagepath;//不在数据库中生成相应的字段
	
	//@Id,设置主键可以标注在属性上面,也可以标注在get方法上面,通常标识在get方法上面
	//@GeneratedValue设置主键增长类型,AUTO是默认值,可以省略,JPA只提供整形自增长方式,没有提供uuid的增长方式
	@Id @GeneratedValue(strategy=GenerationType.AUTO)
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	
	//设置字段的规范:length,字段长度;nullable,非空;name,字段名称;
	@Column(length=10,nullable=false,name="personname")
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	//设置时间在数据库中的格式
	@Temporal(TemporalType.DATE)
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	
	//枚举类型
	@Enumerated(EnumType.STRING) @Column(length=5,nullable=false)
	public Gender getGender() {
		return gender;
	}
	public void setGender(Gender gender) {
		this.gender = gender;
	}
	
	//@Lob标明info在数据库的字段是大文本类型
	@Lob
	public String getInfo() {
		return info;
	}
	public void setInfo(String info) {
		this.info = info;
	}
	
	//@Lob标明file在数据库的字段是存放二进制类型
	//@Basic(fetch=FetchType.LAZY)标识该字段延迟加载,一般用于大内存数据
	@Lob @Basic(fetch=FetchType.LAZY)
	public Byte[] getFile() {
		return file;
	}
	public void setFile(Byte[] file) {
		this.file = file;
	}
	
	//@Transient标明不在数据库中生成相应的字段
	@Transient
	public String getImagepath() {
		return imagepath;
	}
	public void setImagepath(String imagepath) {
		this.imagepath = imagepath;
	}
	
}

枚举类:

package com.zwp.bean;
//性别的枚举
public enum Gender {
	MAN,WOMEN
}

4、测试类:基本的JPA的增删改查

(1)添加Person对象:

	//添加操作
	@Test
	public void save(){	
		//创建factory,方法的参数是持久化单元的名称,在此时创建数据库的表
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		//得到EntityManager对象
		EntityManager entityManager=factory.createEntityManager();
		//开始事务
		entityManager.getTransaction().begin();
		
		entityManager.persist(new Person("小明"));//此时是new状态
		
		//提交事务
		entityManager.getTransaction().commit();
		//关闭
		entityManager.close();
		factory.close();	
	}

(2)获取对象:

	//获取数据1
	@Test
	public void getPerson(){	
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		EntityManager entityManager=factory.createEntityManager();
		//开始事务:	//读取数据是不需要开启事务的,只有需要修改数据库中的内容的时候才需要开启事务
		
		Person person =entityManager.find(Person.class,1);//此时是managed托管状态
		
		//执行业务操作,用了一分钟,如果有人在这个时间段更改了数据,则使用刷新方法。
		entityManager.refresh(person);//刷新数据,不能重新使用find方法,因为只会去一级缓存里面找,因此不会更新数据
		
		System.out.println(person.getName());

		//关闭
		entityManager.close();
		factory.close();	
	}
//获取数据2:延迟加载
	@Test
	public void getPerson2(){	
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		EntityManager entityManager=factory.createEntityManager();
		
		//延时加载:
		Person person =entityManager.getReference(Person.class,1);//此时得到的是一个代理对象,没有装载数据
		System.out.println(person.getName());//在访问的时候才会去装载数据,如果在person对象不存在,再此处访问会抛出异常
		
		//关闭
		entityManager.close();
		factory.close();	
	}

(3)修改对象:

	//更新操作1
	@Test
	public void update(){	
		//创建factory,方法的参数是持久化单元的名称,在此时创建数据库的表
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		//得到EntityManager对象
		EntityManager entityManager=factory.createEntityManager();
		//开始事务
		entityManager.getTransaction().begin();
		
		Person person=entityManager.find(Person.class, 1);//此时实体对象是managed托管状态
		person.setName("小张");//先查再修改
		
		//提交事务
		entityManager.getTransaction().commit();
		//关闭
		entityManager.close();
		factory.close();	
	}
//更新操作2
	@Test
	public void update2(){	
		//创建factory,方法的参数是持久化单元的名称,在此时创建数据库的表
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		//得到EntityManager对象
		EntityManager entityManager=factory.createEntityManager();
		//开始事务
		entityManager.getTransaction().begin();
		
		Person person=entityManager.find(Person.class, 1);//此时实体对象是managed托管状态
		entityManager.clear();//把实体管理器中的所有实体变成游离状态
		person.setName("维鹏");
		entityManager.merge(person);//把实体变成托管状态,如果不变回托管状态,数据不会同步到数据库中
		
		//提交事务
		entityManager.getTransaction().commit();
		
		//关闭
		entityManager.close();
		factory.close();	
	}

(4)删除对象:

//删除操作
	@Test
	public void delete(){	
		//创建factory,方法的参数是持久化单元的名称,在此时创建数据库的表
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		//得到EntityManager对象
		EntityManager entityManager=factory.createEntityManager();
		//开始事务
		entityManager.getTransaction().begin();
		
		Person person=entityManager.find(Person.class, 1);//此时实体对象是managed托管状态
		entityManager.remove(person);//先查再删
		
		//提交事务
		entityManager.getTransaction().commit();
		
		//关闭
		entityManager.close();
		factory.close();	
	}

(5)在上面的几个测试例子中,提到了实体类的三种不同的状态,包含:New状态、manager托管状态、游离状态。感兴趣的可以自己再去了解一下。

5、测试类:JPQL语句:Query对象的增删改查:

(1)查询语句:

        //JPQL:
	//query查询操作:
	@Test
	public void query(){	
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		EntityManager entityManager=factory.createEntityManager();
		entityManager.getTransaction().begin();
		
		//取得集合对象
		Query query=entityManager.createQuery("select o from Person o");
		List<Person> list=query.getResultList();//得到一个集合对象,通过遍历得到里面的数据
		for(Person person:list){
			System.out.println(person.getName());
		}
		
		//取得单一对象
		//3:表示问号的索引值
		Query query1=entityManager.createQuery("select o from Person o where o.id =?3");
		query1.setParameter(3, 1);//第一个参数是问号的索引,第二个参数是id值
		Person person=(Person) query1.getSingleResult();//获得单一数据//相当于hibernate的session.createQuery.uniqueResult();
		System.out.println(person.getName());
		
		//取得统计对象:
		Query query2=entityManager.createQuery("select count(o) from Person o");
		Long lcount=(Long) query2.getSingleResult();//相当于hibernate的session.createQuery.uniqueResult();
		int count=lcount.intValue();//先转成Lon类型再转成int类型
		System.out.println(count);
				
		entityManager.getTransaction().commit();	
		entityManager.close();
		factory.close();	
	}

(2)修改语句:

	//query修改操作:
	@Test
	public void updatequery(){	
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		EntityManager entityManager=factory.createEntityManager();
		entityManager.getTransaction().begin();
		
		Query query=entityManager.createQuery("update Person o set o.name=:name where o.id=:id");
		query.setParameter("name", "xxx");
		query.setParameter("id", 1);
		query.executeUpdate();
		
		entityManager.getTransaction().commit();	
		//关闭
		entityManager.close();
		factory.close();	
	}

(3)删除语句:

//query删除操作
	@Test
	public void deletequery(){	
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
		EntityManager entityManager=factory.createEntityManager();
		entityManager.getTransaction().begin();
		
		Query query=entityManager.createQuery("delete from Person o where o.id=?1");
		query.setParameter(1, 1);
		query.executeUpdate();
		
		entityManager.getTransaction().commit();	
		//关闭
		entityManager.close();
		factory.close();	
	}

至此,一个简单的JPA增删改查程序就完成了。

这个小DEMO中,获取EntityManagerFactory对象的方式,是通过persistence.xml文件手动获取的。在下篇博客将介绍另一种获取EntityManagerFactory对象的方式,即通过Spring注入方式获取。

第二种方式可以看这篇博客:https://blog.csdn.net/a745233700/article/details/81415550

 

三、搭建SSH+JPA+Mysql整合项目:

SSH框架的搭建以及与Mysql数据库的整合这里就不进行介绍了,感兴趣的可以参考这篇博客:

https://blog.csdn.net/a745233700/article/details/81193652

这个主要介绍JPA与SSH的整合:

1、添加hibernate-entitymanager的maven依赖:

	<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

2、创建并编写persistence.xml文件:

注意文件的路径和文件名,参看上面的程序写道的路径和命名(因为数据源在其他地方配置,所有该文件很简洁)

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">  
  
	<persistence-unit name="myjpa" transaction-type="RESOURCE_LOCAL">  
	   <properties>  
		    <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />  
		    <property name="hibernate.max_fetch_depth" value="3" />  
	   </properties>  
	</persistence-unit>
</persistence>

3、配置EntityManagerFactory:

数据源保持不变,但是FactoryBean由LocalSessionFactoryBean改成LocalContainerEntityManagerFactoryBean:

	<!-- SSH与JPA整合:FactoryBean,由LocalSessionFactoryBean改成LocalContainerEntityManagerFactoryBean -->
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<!-- 读取src目录下META-INF下的persistence.xml,value值是persistence-unit标签的name的值 -->
		<property name="persistenceUnitName" value="myjpa"/>  
                <!-- 数据源 -->
		<property name="dataSource" ref="dataSource" />
		<!-- 配置JPA提供商的适配器 -->
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
		</property>
		<!-- 配置JPA基本属性 -->
		<property name="jpaProperties">
                    <props>
                        <prop key="hibernate.show_sql">true</prop>
                        <prop key="hibernate.format_sql">true</prop>
                        <prop key="hibernate.hbm2ddl.auto">update</prop>
                    </props>
                 </property>
                <!-- 配置实体类所在的路径 -->
		<property name="packagesToScan" value="com.zwp.jpa.domain" />
	</bean>

4、配置事务管理器:

	<!-- SSH与JPA整合,事务管理器改为JPA的事务管理器 -->
	<!-- 配置JPA的事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"></property>
    </bean>

5、创建实体类进行测试:

在路径com.zwp.jpa.domain下创建实体类Student:

@Component
@Table(name="T_student")
@Entity
public class Student {
	
	@Id
	private Integer id;
	private String name;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

5、部署项目,看数据库是否产生T-student表,如果有,则成功,反之,失败。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114706.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(1)


相关推荐

  • pycharm怎么用啊_我不想用失去来教会你

    pycharm怎么用啊_我不想用失去来教会你一、PyCharm设置中文(无需汉化包)1、点击左上角的File选项2、选择Settings选项3、点击Plugins选项,等待一会儿,页面出来比较慢。

  • 不吹不擂,你想要的Python面试都在这里了【315+道题】

    不吹不擂,你想要的Python面试都在这里了【315+道题】

    2021年10月22日
  • JVM 内存结构基于JDK1.8【JVM篇三】

    JVM 内存结构基于JDK1.8【JVM篇三】在我的上一篇文章别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】中,相信大家已经对java类加载机制有一个比较全面的理解了,那么类加载之后,字节码数据在Java虚拟机内存中是如何存放的?Java虚拟机在为类实例或成员变量分配内存是如何分配的?是的,这两个问题就涉及到了JVM内存结构的知识了,那么这篇文章将进行解答。文章目录1、内存结构还…

  • setLayout()和GridData的设置[通俗易懂]

    setLayout()和GridData的设置[通俗易懂]总结:(1)setLayout()是设置界面布局,如界面有几行几列如jf.setLayout(newGridLayout(2,1));//容器共有2行1列。GridLayoutlayout=newGridLayout();layout.numColumns=4;//设置容器的列数layout.makeColumnsEqualWidth=false;//设…

  • Go语言开发环境_如何搭建语言培训平台

    Go语言开发环境_如何搭建语言培训平台前言:在《高效能人士的七个习惯》一书中有这么一句话“学而不做等于没学,知而不做等于无知”,所以学习一门新语言光看是不行的,必须身体力行才可以,如果不实践的话最终也只是无知的状态。对于学习语言来说,“做”对应的是编码、调试、运行等,在进行这些工作之前,我们必须安装好编码和调试用的编辑器,运行所需的环境等,这篇文章便是和大家介绍关于go语言开发的环境搭建。一、安装go语言开发包1….

    2022年10月12日
  • python进阶(18)@wraps装饰器[通俗易懂]

    python进阶(18)@wraps装饰器[通俗易懂]前言我们都知道装饰器的作用是在不改变原有的代码基础上,添加新的功能,但是这样会有一个弊端,被装饰的函数某些属性会变改变,接下来我们来看下案例importtimedefrun_time(fu

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号