尝试在db中插入新对象时为什么出现错误?

时间:2020-01-18 19:10:34

标签: java mysql hibernate spring-boot jpa

我的情况如下

用户可以具有一个跟踪列表,与之相对应,跟踪实体包含一个用户ID。({{1} })

每创建一个新曲目,曲目列表就会更新。

上述实体如下:

跟踪实体

@OneToMany

用户实体

@Entity
@Table(name ="track")
public class Track {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long trackId;

@ManyToOne
@JoinColumn(name = "userId", nullable = false)
private User user;

@OneToOne(mappedBy = "track")
private Share share;

private String trackName;

@OneToMany(mappedBy = "pointId")
private List<Point> point;

@OneToOne(mappedBy = "track")
private TrackStatistic trackStatistic;

@Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name = "USER_ID") private Long id; private String firstName; private String lastName; @Column(unique = true) private String username; private String password; @Column(unique = true) private String email; @Column(unique = true) private String phoneNumber; private int age; private Role role; @OneToMany(mappedBy = "shareId") private List<Share> shares; @OneToMany(mappedBy = "trackId") private List<Track> tracks; } 方法如下

createTrack

请注意,public Track createTrack(String username, TrackDTO trackDTO) { //Find user User user = userRepository.findByUsername(username); //Convert Dto to Entity Track track = modelMapper.map(trackDTO, Track.class); //Update user track list user.getTracks().add(track); //Update track track.setUser(user); //save user userRepository.save(user); //save track return trackRepository.save(track); } 是Track实体的相应Dto类


我运行TrackDTO时遇到以下错误:

createTrack

4 个答案:

答案 0 :(得分:1)

已编辑


通过有效的级联,当您保存User时,无需再次保存Track。因此我对您的代码进行了如下更改,希望对您有所帮助

1-将cascade = CascadeType.ALL添加到用户实体

2-将targetEntity = Track .class, mappedBy = "user"添加到用户实体

3-将@ManyToOne(targetEntity = User.class) @JoinColumn(name = "USER_FK")添加到跟踪实体

4-删除trackRepository.save(track);

5-只需保存用户(userRepository.save(user))。通过级联,它也可以保存轨道。

6-返回用户列表中的最后一个曲目。(最新保存的曲目)


我对上述修改进行了编码

用户实体

@Entity
@Table(name = "user")
public class User {

  //other properties

   @OneToMany(targetEntity = Track.class , mappedBy = "user" ,cascade = CascadeType.ALL)
   private List<Track> tracks;

   //getters and setters   
  
  }

跟踪实体

@Entity
@Table(name ="track")
public class Track {
 
//other properties

@ManyToOne(targetEntity = User.class)
@JoinColumn(name = "USER_FK",nullable = false)
private User user;

//getters and setters

}

createTrack方法

public Track createTrack(String username, TrackDTO trackDTO) {

    //Find user
    User user = userRepository.findByUsername(username);

    //Convert Dto to Entity
    Track track = modelMapper.map(trackDTO, Track.class);

    //Update User and Track
    user.getTracks().add(track);
    track.setUser(user);

    //save user
    User result = userRepository.save(user);
    
    //find saved track (you can fetch track by other ways too)
    Track savedTrack = result.getTracks().get(result.getTracks().size()-1);

    return savedTrack;
}

答案 1 :(得分:0)

这种关系是循环的,用户包含轨道,轨道包含用户。双向都有fk约束,所以这个问题。您可以通过保持用户独立性(不涉及跟踪)并保持跟踪引用用户来解决此问题。还有其他解决关系的方法,要删除的要点是避免循环关系

答案 2 :(得分:0)

您应该将曲目保存在用户之前。

// Create XML document
xml_document<> doc;
xml_node<> * root_node;

// Read the xml file into a vector
ifstream theFile (fqn_file);
vector<char> buffer((istreambuf_iterator<char>(theFile)), istreambuf_iterator<char>());
buffer.push_back('\0');

// Parse the buffer using the xml file parsing library into doc
doc.parse<0>(&buffer[0]);

// Find root node
root_node = doc.first_node("ActionMaps");

// Iterate over 'ActionMaps' subtree
for (xml_node<> * actionmap_node = root_node->first_node("actionmap"); actionmap_node; actionmap_node = actionmap_node->next_sibling())
{
    wxLogMessage("I found name subsection %s ",
        actionmap_node->first_attribute("name")->value());

    // Iterate over 'action' subtree
    for(xml_node<> * action_node = actionmap_node->first_node("action"); action_node; action_node = action_node->next_sibling())
    {
        wxLogMessage("I found action name %s ",
            action_node->first_attribute("name")->value());

        // Iterate over 'rebind' subtree
        for(xml_node<> * rebind_node = action_node->first_node("rebind"); rebind_node; rebind_node = rebind_node->next_sibling())
        {
            wxLogMessage("I found key %s ",
                rebind_node->first_attribute("input")->value());
        }
    }
}

如果是普通的旧SQL查询,您的代码将出错:

  • (1)查询将执行20:19:17: I found name subsection spaceship_general 20:19:17: I found action name v_toggle_all_doorlocks 20:19:17: I found key kb1_lshift+l 20:19:17: I found name subsection spaceship_view 20:19:17: I found action name v_view_dynamic_focus 20:19:17: I found key js1_slider1 20:19:17: I found action name v_view_look_behind 20:19:17: I found key js1_button8 20:19:17: I found name subsection spaceship_movement 20:19:17: I found action name v_accel_range_rel 20:19:17: I found key js1_rotx 20:19:17: I found action name v_afterburner 20:19:17: I found key js1_button30 20:19:17: I found action name v_autoland 20:19:17: I found key js1_button14 20:19:17: I found action name v_brake 20:19:17: I found key js1_button7 20:19:17: I found action name v_ifcs_toggle_cruise_control 20:19:17: I found key js1_button12 20:19:17: I found action name v_ifcs_toggle_esp 20:19:17: I found key js1_button11 20:19:17: I found action name v_ifcs_toggle_gforce_safety 20:19:17: I found key js1_button10 20:19:17: I found action name v_ifcs_toggle_speed_limiter 20:19:17: I found key js1_button9 20:19:17: I found action name v_ifcs_toggle_vector_decoupling 20:19:17: I found key js1_button6 20:19:17: I found action name v_roll 20:19:17: I found key js1_x 20:19:17: I found action name v_speed_range_rel 20:19:17: I found key js1_roty 20:19:17: I found action name v_strafe_back 20:19:17: I found key js1_ 20:19:17: I found action name v_strafe_down 20:19:17: I found key js1_button22 20:19:17: I found action name v_strafe_forward 20:19:17: I found key js1_ 20:19:17: I found action name v_strafe_left 20:19:17: I found key js1_button23 20:19:17: I found action name v_strafe_longitudinal 20:19:17: I found key js1_z 20:19:17: I found action name v_strafe_right 20:19:17: I found key js1_button21 20:19:17: I found action name v_strafe_up 20:19:17: I found key js1_button20 20:19:17: I found action name v_target_match_vel 20:19:17: I found key js1_button28 20:19:17: I found action name v_toggle_landing_system 20:19:17: I found key js1_button13 20:19:17: I found action name v_toggle_vtol 20:19:17: I found key js1_button14 20:19:17: I found action name v_yaw 20:19:17: I found key js1_rotz 20:19:17: I found name subsection spaceship_targeting 20:19:17: I found action name v_target_cycle_all_back 20:19:17: I found key js1_hat1_down 20:19:17: I found action name v_target_cycle_all_fwd 20:19:17: I found key js1_hat1_up 20:19:17: I found action name v_target_cycle_friendly_back 20:19:17: I found key js1_button19 20:19:17: I found action name v_target_cycle_friendly_fwd 20:19:17: I found key js1_button17 20:19:17: I found action name v_target_cycle_hostile_back 20:19:17: I found key js1_hat1_left 20:19:17: I found action name v_target_cycle_hostile_fwd 20:19:17: I found key js1_hat1_right 20:19:17: I found action name v_target_cycle_subitem_back 20:19:17: I found key js1_button18 20:19:17: I found action name v_target_cycle_subitem_fwd 20:19:17: I found key js1_button16 20:19:17: I found name subsection spaceship_weapons 20:19:17: I found action name v_attack1_group2 20:19:17: I found key js1_button5 20:19:17: I found name subsection spaceship_missiles 20:19:17: I found action name v_weapon_arm_missile 20:19:17: I found key js1_button2 20:19:17: I found action name v_weapon_launch_missile 20:19:17: I found key js1_button2 20:19:17: I found name subsection spaceship_defensive 20:19:17: I found action name v_weapon_cycle_countermeasure_fwd 20:19:17: I found key js1_button3 20:19:17: I found action name v_weapon_launch_countermeasure 20:19:17: I found key js1_button4 ,但是在保存用户时,public Track createTrack(String username, TrackDTO trackDTO) { User user = userRepository.findByUsername(username); Track track = modelMapper.map(trackDTO, Track.class); user.getTracks().add(track); track.setUser(user); userRepository.save(user); // 1 return trackRepository.save(track); // 2 } 尚未保存,因此由于缺少ID,因此您无法分配给用户/跟踪关系。
  • 第(2)个查询将执行insert into USER_TRACK (<USER>, <TRACK>)并生成一个id,但之后会发生。

您可能会缺少一些JPA映射,因为我认为JPA通常会为您解决这个问题。

答案 3 :(得分:0)

重构实体之间的关系,问题仍然存在。作为轨道和用户之间关系的一个小预览,如下所示: 跟踪实体

import SceneKit

class Cube : SCNNode {

    let cubeWidth:Float = 0.95
    let spaceBetweenCubes:Float = 0.05
    var cubecolor:UIColor = UIColor.black
    var masterCubeDict: [SCNNode: CubeDetails] = [:]

    struct CubeDetails {
        var color:String
        var position:SCNVector3
    }


    override init() {

        super.init()

        let cubeOffsetDistance = self.cubeOffsetDistance()

        var cubeColorString: String = ""

        var xPos:Float = -cubeOffsetDistance
        var yPos:Float = -cubeOffsetDistance
        var zPos:Float = -cubeOffsetDistance

        let xFloor:Float = -1.5
        let yFloor:Float = -1.5
        let zFloor:Float = -1.5
        let floorGeo = SCNBox(width: 20, height: 0, length: 20, chamferRadius: 0)
        let floor = SCNNode(geometry: floorGeo)
        floor.position = SCNVector3(x: xFloor, y: yFloor, z: zFloor)
        floor.name = "floor"
        floor.opacity = 0.0
        floor.physicsBody = SCNPhysicsBody(type: .kinematic, shape: nil)
        floor.physicsBody?.collisionBitMask = 1
        floor.physicsBody?.friction = 1.0
        self.addChildNode(floor)

        for _  in 0..<5 {
           for _ in 0..<5 {
                for _ in 0..<5 {
                    let cubeGeometry = SCNBox(width: CGFloat(cubeWidth), height: CGFloat(cubeWidth), length: CGFloat(cubeWidth), chamferRadius: 0)
                    let material = SCNMaterial()
                    material.diffuse.contents = randomColor()

                    //unwrap material (type any) and cast to uicolor for switch
                    if let unwrapColor: UIColor = material.diffuse.contents as? UIColor {

                        switch unwrapColor {
                        case UIColor.red:
                             cubeColorString = "red"
                        case UIColor.green:
                             cubeColorString = "green"
                        case UIColor.blue:
                             cubeColorString = "blue"
                        default:
                             cubeColorString = "black"
                        }
                    } else { print("Error unwrapping color") }

                    cubeGeometry.materials = [material, material, material, material, material, material]

                    let cube = SCNNode(geometry: cubeGeometry)
                    cube.name = cubeColorString
                    cube.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
                    cube.physicsBody?.restitution = 0.0
                    cube.physicsBody?.isAffectedByGravity = true
                    cube.physicsBody?.mass = 25.0
                    cube.physicsBody?.friction = 1.0
                    cube.physicsBody?.collisionBitMask = 1
                    cube.position = SCNVector3(x: xPos, y: yPos, z: zPos)

                    let details = CubeDetails(color: cubeColorString, position: cube.position)

                    //add cube details to the master dict
                    masterCubeDict[cube] = details

                    //print(masterCubeDict)


                    xPos += cubeWidth + spaceBetweenCubes
                    self.addChildNode(cube)
                }
                xPos = -cubeOffsetDistance
                yPos += cubeWidth + spaceBetweenCubes
            }
            xPos = -cubeOffsetDistance
            yPos = -cubeOffsetDistance
            zPos += cubeWidth + spaceBetweenCubes
        }
    }

    private func cubeOffsetDistance()->Float {
       return (cubeWidth + spaceBetweenCubes) / 2
    }

    private func randomColor() -> UIColor{
        var tmpColor: UIColor
        let num = Int.random(in:0...2)

        switch num {
        case 0:
            tmpColor = UIColor.red
        case 1:
            tmpColor = UIColor.blue
        case 2:
            tmpColor = UIColor.green
        default:
            tmpColor = UIColor.black
        }
        return tmpColor
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

用户实体

GameViewController

,创建轨道时调用的方法是:

import UIKit
import QuartzCore
import SceneKit

var myMasterCubeDict: [SCNNode: Cube.CubeDetails] = [:]

class GameViewController: UIViewController {

    let gameCube = Cube()

    override func viewDidLoad() {
        super.viewDidLoad()

        // create a new scene
        // let scene = SCNScene(named: "art.scnassets/ship.scn")!

        let scene = SCNScene()

        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 2, y: 0, z: 20)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // init cube
        myMasterCubeDict = gameCube.masterCubeDict
        scene.rootNode.addChildNode(gameCube)


        // retrieve the SCNView
        let scnView = self.view as! SCNView

        // set the scene to the view
        scnView.scene = scene


        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = UIColor.black


        // add a tap gesture recognizer
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        scnView.addGestureRecognizer(tapGesture)
    }

    @objc
    func handleTap(_ gestureRecognize: UIGestureRecognizer) {
        // retrieve the SCNView
        let scnView = self.view as! SCNView
        // check what nodes are tapped
        let p = gestureRecognize.location(in: scnView)
        let hitResults = scnView.hitTest(p, options: [:])
        // check that we clicked on at least one object
        if hitResults.count > 0 {
            // retrieved the first clicked object
            let result = hitResults[0]

            //get dict of same-color node
            var dictOfSameColor = findAndReturnChain(boi: result.node)
            //  print(dictOfSameColor)
            var finalNodes: [SCNNode] = [result.node]
            var resFlag = 1
            repeat {
                var xSame: Bool = false
                var ySame: Bool = false
                var zSame: Bool = false
                resFlag = 0
                for node in finalNodes {
                   // var nodeX = node.position.x
                    for (key, value) in dictOfSameColor {

                        if(abs(node.position.x - value.position.x) < 0.7)  {
                             xSame = true
                        }
                        if(abs(node.position.y - value.position.y) < 0.7) {
                             ySame = true
                        }
                        if(abs(node.position.z - value.position.z) < 0.7) {
                             zSame = true
                        }
                        //print("X-val: \(xDif) \nY-val: \(yDif) \nZ-val: \(zDif) \nColor: \(key.name) \n\n\n\n")
                        if (xSame && ySame ) {
                                if !(zSame) {
                                    if (abs((node.position.z-value.position.z)) < 2) {
                                    finalNodes.append(key)
                                    dictOfSameColor.removeValue(forKey: key)
                                    resFlag = 1
                                    }
                                }
                        }

                        if (xSame && zSame) {
                                  if !(ySame) {
                                    if (abs((node.position.y-value.position.y)) < 2) {
                                      finalNodes.append(key)
                                      dictOfSameColor.removeValue(forKey: key)
                                      resFlag = 1
                                    }
                                  }
                          }

                        if (ySame && zSame) {
                                  if !(xSame) {
                                    if (abs((node.position.x-value.position.x)) < 2) {
                                      finalNodes.append(key)
                                      dictOfSameColor.removeValue(forKey: key)
                                      resFlag = 1
                                    }
                                  }
                          }
                        xSame = false
                        ySame = false
                        zSame = false

                    }

                }

            //print(finalNodes)
            } while resFlag == 1

            //print(finalNodes)

            for node in finalNodes {
                if node.name != "floor" {
                node.removeFromParentNode()
                }
            }
            //IMPLEMENT: Reset dicts to current state of the cube
            myMasterCubeDict = updateMasterCubeDict(cube: gameCube)
            dictOfSameColor.removeAll()
        }




    }



    func findAndReturnChain(boi: SCNNode) -> [SCNNode:Cube.CubeDetails] {
        var ret: [SCNNode:Cube.CubeDetails] = [:]
        //find cubes with the same color
        for (key, value) in myMasterCubeDict {
            if value.color == boi.name {
                ret[key] = value
            }
        }

        return ret
    }

    func updateMasterCubeDict(cube: Cube) -> [SCNNode:Cube.CubeDetails] {
        myMasterCubeDict.removeAll()
        var newNode: SCNNode = SCNNode()
        var newDetails = Cube.CubeDetails(color: "", position: SCNVector3Zero)

        cube.enumerateChildNodes { (cube, stop) in
            newNode = cube
            if let newName = cube.name {
                newDetails.color = newName
            }
            newDetails.position = cube.position
            myMasterCubeDict[newNode] = newDetails
        }

        return myMasterCubeDict
    }


    override var shouldAutorotate: Bool {
        return true
    }

    override var prefersStatusBarHidden: Bool {
        return true
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if UIDevice.current.userInterfaceIdiom == .phone {
            return .allButUpsideDown
        } else {
            return .all
        }
    }
}

所以问题出在轨道列表上的@JoinColumn批注中,我将名称为 TRACK_ID 而不是 USER_ID