JPA方言问题

4 篇文章 0 订阅

1.基本说明

JPA方言问题,是在进行JPA开发时,可能遇到的问题。主要遇到问题的场景为:JPA由于要适应不同数据库,而不同数据库表结构和数据类型存在的一定的区别,从而造成方言问题。

JPA的方言问题的表现主要为:JAVA之中的Bean类与SQL语句转换过程中,存在转化失败的问题。

JPA方言的最可能出问题的地方在调用原生的SQL语句时,此时由于导出的表类型与Java的Bean类型不一致,造成设置类型错误而无法运行。

2.基本解决方案:persistence.xml文件修改

更改persistence.xml文件,是解决问题的基本思路。不同数据库,对应不同的方言;而且,不同的数据库有不同的官方方言库。

官方库或官方类对应的参数配置为hibernate.dialect,建议SQL Server选择SQLServer2012Dialect,MySQL选择MySQL8Dialect。

具体样例参考下面所示。

 <!--定义数据库连接的相关属性 -->
<!--            <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2012Dialect" />-->             
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect" /> 
<!--            <property name="hibernate.dialect" value="org.hibernate.dialect.SybaseDialect" />--

3.解决方案1:建造适合新数据的Bean

如果已经使用了官方Dialect,在调用官方导出类的适合,一般不会出问题。真正出问题可能在使用原生的SQL语句的时候。当JAVA调用原生的SQL语句时,可能会有导出的数据类型和JAVA类的Bean类型不一致,造成类型设置错误。

错误样例如下:

String sql = “SQL语句”;
NativeQueryImpl queryImpl =  em.createNativeQuery(sql).unwrap(NativeQueryImpl.class);
queryImpl.setResultTransformer(Transformers.aliasToBean(A.class));

List<A> db = queryImpl.getResultList();

如果A中的某一变量或属性和导出数据不匹配,会造成设置数据错误。

更改方法如下:

解决方案为,对原有类进行复制,建立ACopy类,对发生错误的属性进行setter函数更改。

代码如下:

public class A { 
    //在某些数据库,如MySQL中就会出问题,因为用原生的SQL,导出的数据库表的类型为Byte
    public Boolean key;

    public Boolean getKey() {
        return key;
    }

    public void setKey(Boolean key) {
        this.key = key;
    }
}

public class ACopy { 
    //在某些数据库,如MySQL中就会出问题,因为用原生的SQL,导出的数据库表的类型为Byte
    public Boolean key;

    public Boolean getKey() {
        return key;
    }

    public void setKey(Byte key) {
        this.key = key;
    }
}

//执行如下的JAVA语句
EntityManagerFactory emf = null; //自己构造
EntityManager em = emf.createEntityManager();

NativeQueryImpl queryImpl = em.createNativeQuery(sql).unwrap(NativeQueryImpl.class);

if(emf.getProperties().get("hibernate.connection.url").toString().toLowerCase().contains("mysql")) {
	queryImpl.setResultTransformer(Transformers.aliasToBean(ACopy.class));
} else {
	queryImpl.setResultTransformer(Transformers.aliasToBean(A.class));
}

List<A> iquery = queryImpl.getResultList();

4.解决方案2:使用Stream方法Map

第二种解决方案时直接用导出的类,调用CriteriaBuilder等语句,生成表。然后,用Stream方法生成类和Map,进行Map映射。

此种方法的缺点为:必须保证Map下的Key和Value是唯一的,否则会造成数据错误。

样例如下(仅作Map说明):

List<ObjA> lstA = new LinkedList<>();
lstA.add(new ObjA("01", "王"));
lstA.add(new ObjA("02", "李"));
lstA.add(new ObjA("03", "张"));
lstA.add(new ObjA("04", "刘"));

List<ObjB> lstB = new LinkedList<>();
lstB.add(new ObjB("01", "Wang"));
lstB.add(new ObjB("02", "Li"));
lstB.add(new ObjB("03", "Zhang"));
lstB.add(new ObjB("04", "Liu"));

Map<String, ObjA> mapA = lstA.stream().collect(Collectors.toMap(ObjA::getId, t -> t));
System.out.println(mapA);

List<ObjC> lstC = new LinkedList<>();

for(ObjB objB: lstB){
	lstC.add(new ObjC(objB.id, mapA.get(objB.id).name, objB.code));
}

System.out.println("test");

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值