如何使用CriteriaUpdate编写联接?

问题描述

我想请帮助我找出更新其他表中外键值的解决方案。 例如:-

如果我们获取了设备表

列是:-设备名 设备编号 显示名称 用户身份 roomId isDeleted

其他表是“房间表”

列是:-roomName roomId 房型 isDeleted

听到它看起来像一对多的关系。 即一间房间将容纳许多设备。

在以上两个表中,roomId是Rooms表中的主键,而roomId是Device表中的原键。 因此,听到我们想要的是我们必须更新DeviceTable中的roomId。 我尝试过,但是,我无法找到解决方案,我要求你们帮我解决这个问题。

数据库表将像

Room Table(room_table)

room_id    room_name    room_type
1           ROOM1       ROOM_TYPE1
2           ROOM2       ROOM_TYPE2

Device Table like(device_table)
device_id     device_name    display_name    room_id
1              DEVICE1        disPLAY1         1
2              DEVICE2        disPLAY2         2

希望你们能理解上表。

所以,现在我要做的任务是:- 我要更新设备表中的roomId,例如,对于DEVICE2,我们必须从以下所示的roomId 1更新为roomId 2。

Device Table like(device_table)
device_id    device_name   display_name    room_id
1             DEVICE1       disPLAY1         1
2             DEVICE2       disPLAY2         2

为此,我编写了如下的Java代码:-

    @Entity
    @Table(name = "device_table")
    public class Device {
        @Id
        @Column(name = "device_id")
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int deviceid;
        @Column(name = "device_name")
        private String deviceName;
        @Column(name = "display_name")
        private String dispalyName;
        @ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
        //private List<Room> roomList = new ArrayList<>();
        @JoinColumn(name = "ROOM_ID")
        private Room roomList; 
         //setters & getters
    }

        @Entity
        @Table(name = "room_table")
        public class Room {
            @Id
            @Column(name = "room_id")
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            private int roomId;
            @Column(name = "room_name")
            private String roomName;
            @Column(name = "room_type")
            private String roomType;
            @OnetoMany(mappedBy="roomList")
            private Collection<Device> deviceList = new ArrayList<>();
      
    
     //setters & getters
}

对于更新,我尝试了如下代码

public class SaveDataClientTest {

    public static void main(String[] args) {
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            session.beginTransaction();
         CriteriaBuilder userBuilder = session.getCriteriaBuilder();
            CriteriaUpdate<Device> deviceUpdate = userBuilder.createCriteriaUpdate(Device.class);
            Root<Device> deviceUpdateRoot = deviceUpdate.from(Device.class);

            Subquery<Device> deviceSubquery = deviceUpdate.subquery(Device.class);
            Root<Device> roomroot = deviceSubquery.from(Device.class);
            Join<Device,Room> join = roomroot.join("roomList",JoinType.LEFT);
            
             deviceUpdate.set(deviceUpdateRoot.get("dispalyName"),"disPLAY12345"); 
            deviceUpdate.set(join.get("roomId"),2);
        
            deviceUpdate.where(userBuilder.equal(deviceUpdateRoot.get("deviceName"),"DEVICE2"));
            int returnValue = session.createquery(deviceUpdate).executeUpdate();
            System.out.println(returnValue);

            session.getTransaction().commit();
        } catch (HibernateException e) {
            e.printstacktrace();
        }
    }
}

我遇到类似的错误

Oct 01,2020 8:00:03 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Oct 01,2020 8:00:03 PM org.hibernate.hql.internal.ast.ErrorCounter reportError
ERROR:  Invalid path: 'generatedalias1.roomId'
Oct 01,2020 8:00:03 PM org.hibernate.hql.internal.ast.ErrorCounter reportError
ERROR:  Invalid path: 'generatedalias1.roomId'
 Invalid path: 'generatedalias1.roomId'
    at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)
    at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:214)
    at org.hibernate.hql.internal.ast.HqlsqlWalker.resolve(HqlsqlWalker.java:1038)
    at org.hibernate.hql.internal.ast.HqlsqlWalker.resolve(HqlsqlWalker.java:1026)
    at org.hibernate.hql.internal.antlr.HqlsqlbaseWalker.assignment(HqlsqlbaseWalker.java:1054)
    at org.hibernate.hql.internal.antlr.HqlsqlbaseWalker.setClause(HqlsqlbaseWalker.java:765)
    at org.hibernate.hql.internal.antlr.HqlsqlbaseWalker.updateStatement(HqlsqlbaseWalker.java:381)
    at org.hibernate.hql.internal.antlr.HqlsqlbaseWalker.statement(HqlsqlbaseWalker.java:269)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:266)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
    at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:553)
    at org.hibernate.internal.AbstractSharedSessionContract.createquery(AbstractSharedSessionContract.java:662)
    at org.hibernate.internal.SessionImpl.createquery(SessionImpl.java:3324)
    at org.hibernate.query.criteria.internal.AbstractManipulationCriteriaQuery$1.buildCompiledQuery(AbstractManipulationCriteriaQuery.java:112)
    at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
    at org.hibernate.internal.SessionImpl.createquery(SessionImpl.java:3628)
    at org.hibernate.internal.SessionImpl.createquery(SessionImpl.java:203)
    at com.infotech.client.SaveDataClientTest.main(SaveDataClientTest.java:54)

Exception in thread "main" java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedalias1.roomId' [update com.infotech.entities.Device as generatedalias0 set generatedalias0.dispalyName = :param0,generatedalias1.roomId = 2 where generatedalias0.deviceName=:param1]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:133)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)
    at org.hibernate.internal.AbstractSharedSessionContract.createquery(AbstractSharedSessionContract.java:670)
    at org.hibernate.internal.SessionImpl.createquery(SessionImpl.java:3324)
    at org.hibernate.query.criteria.internal.AbstractManipulationCriteriaQuery$1.buildCompiledQuery(AbstractManipulationCriteriaQuery.java:112)
    at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
    at org.hibernate.internal.SessionImpl.createquery(SessionImpl.java:3628)
    at org.hibernate.internal.SessionImpl.createquery(SessionImpl.java:203)
    at com.infotech.client.SaveDataClientTest.main(SaveDataClientTest.java:54)
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedalias1.roomId' [update com.infotech.entities.Device as generatedalias0 set generatedalias0.dispalyName = :param0,generatedalias1.roomId = 2 where generatedalias0.deviceName=:param1]
    at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
    at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:272)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
    at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:553)
    at org.hibernate.internal.AbstractSharedSessionContract.createquery(AbstractSharedSessionContract.java:662)
    ... 6 more

请您帮我解决这个问题。 谢谢。

解决方法

您尝试过以下吗?

        CriteriaUpdate<Device> deviceUpdate = userBuilder.createCriteriaUpdate(Device.class);
        Root<Device> deviceUpdateRoot = deviceUpdate.from(Device.class);
        
        deviceUpdate.set(deviceUpdateRoot.get("dispalyName"),"DISPLAY12345"); 
        deviceUpdate.set(deviceUpdateRoot.get("roomList").get("roomId"),2);
    
        deviceUpdate.where(userBuilder.equal(deviceUpdateRoot.get("deviceName"),"DEVICE2"));
        int returnValue = session.createQuery(deviceUpdate).executeUpdate();

还是这个?

        CriteriaUpdate<Device> deviceUpdate = userBuilder.createCriteriaUpdate(Device.class);
        Root<Device> deviceUpdateRoot = deviceUpdate.from(Device.class);
        
        deviceUpdate.set(deviceUpdateRoot.get("dispalyName"),"DISPLAY12345"); 
        deviceUpdate.set(deviceUpdateRoot.get("roomList"),session.getReference(Room.class,2));
    
        deviceUpdate.where(userBuilder.equal(deviceUpdateRoot.get("deviceName"),"DEVICE2"));
        int returnValue = session.createQuery(deviceUpdate).executeUpdate();